std :: map распределители привязаны к кучам для всех ключей и значений? - PullRequest
0 голосов
/ 26 января 2012

Интересно, как я могу создать что-то вроде std::map<T1, T2>(T1allocator, T2allocator, T1deallocator, T2deallocator), чтобы при попытке вставить пару ключей <-> значений в мою карту из любой кучи или изменить некоторые данные в исходной куче создателей карты будут созданы, а нев других кучах, которые пытаются передать в него свои собственные данные?


Скажем, у нас есть библиотека DLL (в Windows), и мы динамически (во время выполнения) присоединяем ее к нашему основному приложению.Эта библиотека (как основное приложение) была скомпилирована со статической средой выполнения.Таким образом, потенциально получим 2 разных STL и 2 разных кучи - один с DLL, другой с App.

Скажем, теперь мы хотим, чтобы наш плагин / dll работал только с памятью из основной кучи приложения.

Давайте перейдем к простому демонстрационному коду.

Мы создали простой интерфейс плагина, известный нашему основному приложению:

class plugin:
{
public:
    virtual void pass_and_modify_data( boost::shared_ptr<std::map<std::string, std::string> >  a) =0;
};

Мы создали библиотеку Pugin DLL с:

#include "plug_in_interface.h"
class my_plugin: public plugin
{
    public:
        virtual void pass_and_modify_data( boost::shared_ptr<std::map<std::string, std::string> >  a)
        {
            a->insert(std::pair<std::string, std::string>("hello", "World"));
            (*a)["world"] = "hello";
        }
};

Теперь мы хотим передать карту из нашего приложения в плагин, но сделать все значения, переданные нашей карте, размещенными в куче главных приложений.

Как это сделать - как заставить std::map перераспределить данныеключи и значения в основной хэш приложения без замечаний разработчика кода плагина?(здесь под замечением я подразумеваю такие вещи, как вставка в строки карт с помощью обычного освобождения или написание какого-либо специального нетривиального кода)


Глядя на sehe's ответ и демонстрацию, которую я хочу создать:

Если я получу его, напишите, что мой main будет выглядеть так:

#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/flyweight.hpp>
#include "plug_in_interface.h"

using namespace boost;
using namespace boost::flyweights;
typedef flyweight<
    std::string,
    hashed_factory<
     boost::hash<std::string>,
    std::equal_to<key_value>,
    std::allocator<boost::mpl::_1> // here we get errors like C2065: 'key_value' : undeclared identifier    
    >
> customString;

int main()
{
 // boring part -  load plugin... into something like boost::shared_ptr<plugin> my_plugin 
 //intresting part - create map in main heap and make all its values and keys be forced to be allocated or reallocated in main heap

    std::cout << std::endl << "Map allocator mased memory management:" << std::endl;
    std::cin.get();
    {
        boost::shared_ptr<std::map<std::string, std::string> > a  (new std::map<customString, customString>());
        my_plugin->pass_and_modify_data(a);
        std::cout << "modified data: " << (*a)["hello"] << (*a)["world"] << std::endl;
    }
    std::cout << "removed data" << std::endl;
    std::cin.get();

  }

В настоящее время я не могу скомпилировать эту вещь из-за способа определения типа customString .. компилятор показывает множество ошибок компилятора.Как сделать тип def более корректным?

Вообще-то, я абсолютно в порядке с stl :: allocators. Единственное, что мне действительно нужно, это чтобы распределитель был каким-то образом привязан к куче (как мы можем сделать с shared_ptrs), такая возможность возможна?

Ответы [ 2 ]

1 голос
/ 26 января 2012

Вы можете использовать Boost Flywheight или Boost Optional.

Хотя они не совсем соответствуют стандартным контейнерам, они допускают стратегии фабрики / распределения, и вы можете использовать это.Конечно, вы получите другой уровень косвенности, который может или не может быть тем, что вы хотите.

Смотрите, например, http://www.boost.org/doc/libs/1_48_0/libs/flyweight/doc/tutorial/configuration.html#factories

hashed_factory<[Hash[,Pred[,Allocator]]]>....

Предположим, мы хотели бы настроить hashed_factory для весового значения std :: string со специальным хеш-предикатом special_hash и настраиваемым распределителем custom_allocator;это будет определено следующим образом:

typedef flyweight<
  std::string,
  hashed_factory<
    special_hash<std::string>,
    std::equal_to<key_value>,
    custom_allocator<boost::mpl::_1>
  >
> customString;

Поскольку мухи по своей природе неизменны , они будут лучше работать для ключей:

 std::map<customString, int> my_funky_map;

Теперь,используйте распределитель карты по умолчанию, чтобы указать, где должны быть расположены элементы (пары) карты.


1 голос
/ 26 января 2012

Если вы просто хотите предоставить функции до map, которые выполняют распределение, вам не повезло.Стандартный способ управления памятью в контейнере STL - allocators .

. Нельзя использовать отдельные распределители для ключей и значений, поскольку std::map принимает только один параметр шаблона распределителя (std::map<Key, Value, Predicate, Allocator>).Но для этого нет никаких причин - для обоих будет достаточно одного распределителя.

Если вы просто хотите использовать специальный распределитель, это просто сделать.Вы можете использовать один из стандартных (alloc, pthread_alloc, single_client_alloc или malloc_alloc) или прочитать этот урок , чтобы научиться писать свои собственные.Если вы сможете предоставить больше информации о том, какую проблему вы пытаетесь решить, возможно, я смогу дать более полезный ответ.

...