将 Boost 享元与共享内存一起使用

Posted

技术标签:

【中文标题】将 Boost 享元与共享内存一起使用【英文标题】:Using Boost flyweight with shared memory 【发布时间】:2013-06-21 17:17:23 【问题描述】:

我想在共享内存中保留大量(经常重复的)字符串,因此我使用了 Boost 的享元和进程间 basic_string 功能。为了确保字符串实际存储在共享内存中,我需要在享元使用的 hashed_factory 中提供自定义分配器。

但是,当我将自定义分配器指定给 hashed_factory 时,它无法编译 (g++ 4.2.1)...可能是因为它需要一个额外的参数来指定段管理器。让这个工作的语法是什么,或者有更好的方法来做到这一点?

#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 cmets 后面的行是有问题的行,注释的版本是有效但未使用正确分配器的行。

【问题讨论】:

【参考方案1】:

看起来你是对的问题是所需的构造函数参数。 hashed_factory docs 说:

hashed_factory_class 所基于的内部散列容器 由 Hash、Pred 和 分配器。

我想知道您是否可以通过创建具有默认构造函数的共享内存分配器的子类,将段管理器传递给基类构造函数来解决此问题。例如,像这样:

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

  MyShmAllocator()
  : ShmFactoryEntryAllocator(*segmentManager) 
  
;

在调用构造函数之前,您需要分配一个“当前”MyShmAllocator::segmentManager。这有点难看,但我认为它应该可以工作。

【讨论】:

我认为这越来越接近了,但我仍然无法完全编译。事实证明,MyShmAllocator 构造函数实际上不应该取消引用指针。但是,在将 ShmStringHashedFactory 切换为使用 MyShmAllocator 之后,它仍然不太高兴...gist.github.com/bovine/5863647 事实证明,您的答案是正确的,但仍然需要一个完整的解决方案,例如拥有一个知道如何存储在共享内存中的持有者类和锁定策略.我的同事在 Boost 邮件列表上提出了同样的问题,并从 Joaquín M López Muñoz 那里得到了非常全面的回答:permalink.gmane.org/gmane.comp.lib.boost.devel/242512

以上是关于将 Boost 享元与共享内存一起使用的主要内容,如果未能解决你的问题,请参考以下文章

Boost:shared_memory_object --- 共享内存

Boost、共享内存和向量

boost::interprocess 共享内存段函数 find() 如果段已经存在,则在启动时挂起

Java开发设计模式 11:享元模式

设计模式之享元

使用 Boost.Interprocess 使进程等待直到资源加载到共享内存中