Использование Boost flyweight с общей памятью

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

Однако это не удается скомпилировать (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 являются проблемными строками, а закомментированные версии — это те, которые работают, но не используют правильный распределитель.


person bovine    schedule 21.06.2013    source источник


Ответы (1)


Похоже, вы правы в том, что проблема заключается в обязательном аргументе конструктора. В 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 перед любым вызовом конструктора. Это немного уродливо, но я думаю, что это должно работать.

person rhashimoto    schedule 24.06.2013
comment
Я думаю, что это приближается, но я все еще не могу это скомпилировать. Как оказалось, конструктор MyShmAllocator на самом деле не должен разыменовывать указатель. Но, тем не менее, после переключения ShmStringHashedFactory на использование MyShmAllocator это все равно не совсем устраивает... крупный рогатый скот/5863647 - person bovine; 26.06.2013
comment
Как оказалось, ваш ответ находится на правильном пути, но для полного решения требуется еще больше, например, наличие класса-держателя, который знает, как хранить в общей памяти, и политики блокировки. Мой коллега задал тот же вопрос в списке рассылки Boost и получил исчерпывающий ответ от Хоакина М. Лопеса Муньоса: permalink.gmane.org/gmane.comp.lib.boost.devel/242512 - person bovine; 26.06.2013