Использование Boost flyweight с общей памятью
Я хотел бы сохранить большое количество (часто дублируемых) строк в разделяемой памяти, поэтому я использую функциональность Boost и межпроцессную базовую_строку. Чтобы убедиться, что строка действительно хранится в разделяемой памяти, мне нужно предоставить собственный распределитель в hashed_factory, используемом 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 являются проблемными, причем закомментированные версии работают, но не используют правильный распределитель.
1 ответ
Похоже, вы правы в том, что проблема является обязательным аргументом конструктора. hashed_factory
документы говорят:
Внутренний хеш-контейнер, на котором основан hashed_factory_class, построен с инициализированными объектами по умолчанию типа Hash, Pred и Allocator.
Интересно, можно ли обойти это, создав подкласс распределителя общей памяти, который имеет конструктор по умолчанию, передавая менеджер сегмента конструктору базового класса. Например, что-то вроде этого:
class MyShmAllocator : public ShmFactoryEntryAllocator {
public:
static boost::interprocess::managed_mapped_file::segment_manager *segmentManager;
MyShmAllocator()
: ShmFactoryEntryAllocator(*segmentManager) {
}
};
Вам нужно будет присвоить "текущий" MyShmAllocator:: сегмент Manager перед любым вызовом конструктора. Это немного некрасиво, но я думаю, что это должно сработать.