2013-06-21 5 views
1

Я хотел бы сохранить большое количество (часто повторяющихся) строк в общей памяти, поэтому я использую функции Boost в flyweight и interprocess basic_string. Чтобы убедиться, что строка фактически хранится в общей памяти, мне нужно предоставить пользовательский распределитель в hashed_factory, используемом мухой.Использование Boost flyweight с разделяемой памятью

Однако это не удается скомпилировать (g ++ 4.2.1), когда я укажу свой пользовательский распределитель на hashed_factory ... вероятно, потому что для указания диспетчера сегментов требуется дополнительный аргумент. Каков синтаксис, чтобы заставить это работать, или есть лучший способ сделать это?

#include <boost/interprocess/managed_mapped_file.hpp> 
#include <boost/interprocess/managed_shared_memory.hpp> 
#include <boost/interprocess/allocators/allocator.hpp> 
#include <boost/interprocess/containers/string.hpp> 
#include <boost/flyweight.hpp> 
#include <boost/flyweight/no_tracking.hpp> 
#include <boost/flyweight/hashed_factory.hpp> 

using namespace boost::flyweights; 
using namespace boost::container; 
using namespace boost::interprocess; 


typedef boost::interprocess::allocator<boost::mpl::_1, boost::interprocess::managed_mapped_file::segment_manager> ShmFactoryEntryAllocator; 

typedef boost::interprocess::allocator<char, boost::interprocess::managed_mapped_file::segment_manager> ShmAllocatorChar; 

typedef boost::interprocess::basic_string<char, std::char_traits<char>, ShmAllocatorChar> ShmString; 

// TODO: using ShmFactoryEntryAllocator does not work 
typedef boost::flyweights::hashed_factory<boost::hash<ShmString>, std::equal_to<ShmString>, ShmFactoryEntryAllocator> ShmStringHashedFactory; 
//typedef boost::flyweights::hashed_factory<boost::hash<ShmString>, std::equal_to<ShmString>, std::allocator<boost::mpl::_1> > ShmStringHashedFactory; 

// TODO: need to be able to use a hashed_factory with our custom allocator. 
typedef boost::flyweights::flyweight<ShmString, ShmStringHashedFactory> ShmFlyweightString; 
//typedef boost::flyweights::flyweight<ShmString> ShmFlyweightString; 


int main(int argc, char** argv) 
{ 
    managed_mapped_file *segment = new managed_mapped_file(create_only, "memory.dat", 409600); 
    ShmFactoryEntryAllocator factoryEntryAllocator(segment->get_segment_manager()); 

    // create a normal string in shared-memory. 
    ShmString *ps1 = segment->construct<ShmString>("s1")("some shm normal string", factoryEntryAllocator); 

    // create a flyweight string in shared memory. 
    ShmFlyweightString *ps2 = segment->construct<ShmFlyweightString>(anonymous_instance)("some shm flyweight string", factoryEntryAllocator); 

    return 0; 
} 

линия после комментариев TODO являются проблемными линиями, с комментируемыми версиями быть те, которые работают, но не использовать правильный аллокатор.

ответ

0

Похоже, вы правы в том, что проблема является требуемым аргументом конструктора. hashed_factory docs говорят:

внутренний Хешированное контейнер, на котором hashed_factory_class основан строится с по умолчанию инициализируются объекты типа Hash, Pred и Allocator.

Мне интересно, можете ли вы обойти это, создав подкласс распределенного распределителя памяти, который имеет конструктор по умолчанию, передавая менеджер сегмента в конструктор базового класса. Например, что-то вроде этого:

class MyShmAllocator : public ShmFactoryEntryAllocator { 
public: 
    static boost::interprocess::managed_mapped_file::segment_manager *segmentManager; 

    MyShmAllocator() 
    : ShmFactoryEntryAllocator(*segmentManager) { 
    } 
}; 

Вы должны назначить «текущий» MyShmAllocator :: segmentManager до вызова конструктора. Это немного уродливо, но я думаю, что это должно сработать.

+0

Я думаю, что все ближе, но я до сих пор не могу получить это, чтобы скомпилировать. Как оказалось, конструктор MyShmAllocator должен фактически не разыменовывать указатель. Но все же, после переключения ShmStringHashedFactory на использование MyShmAllocator он все еще не совсем доволен ... https://gist.github.com/bovine/5863647 – bovine

+0

Как выясняется, ваш ответ на правильном пути, но есть еще больше необходимо для полного решения, такого как наличие класса держателя, который знает, как хранить в общей памяти и политике блокировки. Мой коллега задал этот же вопрос в списке рассылки Boost и получил исчерпывающий ответ от Хоакина М Лопеса Муньоса: http://permalink.gmane.org/gmane.comp.lib.boost.devel/242512 – bovine