共享内存中带有boost :: interprocess分配器的std :: unordered_map-缺点吗? [英] std::unordered_map with boost::interprocess allocator in shared memory - drawbacks?

查看:153
本文介绍了共享内存中带有boost :: interprocess分配器的std :: unordered_map-缺点吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在使用boost::interprocess进入共享内存.

I'm right now getting into shared memory using boost::interprocess.

我已经按照以下方式定义了几种std::unordered_mapstd::unordered_set类型:

I've defined a few std::unordered_map and std::unordered_set types like in the following manner:

#include <boost/interprocess/allocators/allocator.hpp>

#include <unordered_map> // NOT the boost implementation ...

...

namespace ipc = boost::interprocess;

 /**
 * allocator type needed to construct maps in shared memory
 */
typedef ipc::allocator<std::pair<const size_t, std::string>,
           ipc::managed_shared_memory::segment_manager> OBJ_MAP_ALLOCATOR;

/**
 * map type to construct maps in shared memory
 */
typedef std::unordered_map<size_t,
               std::string,
               std::hash<size_t>,
               std::equal_to<size_t>,
               OBJ_MAP_ALLOCATOR> OBJ_MAP_TYPE;

我这样初始化它们:

ipc::managed_shared_memory segment;

// allocate segment etc ... 

OBJ_MAP_ALLOCATOR alloc_inst(segment.get_segment_manager());
objMap = segment.find_or_construct<OBJ_MAP_TYPE> (ipc::unique_instance)(alloc_inst);

这似乎很好用,我在编译或运行时没有发现任何问题(在ma​​cOS,Apple LLVM version 9.1.0 (clang-902.0.39.1)和C ++ 14标准上工作).

This seems to work fine, i haven't found any problems during compile- or runtime (working on macOS, Apple LLVM version 9.1.0 (clang-902.0.39.1), with C++14 standard).

在Boost文档中,仅提及Boost容器或特定于进程间的实现.不幸的是,它们似乎不包含无序版本.

In the Boost documentation, only the Boost containers, or the interprocess-specific implementations are mentioned. Unfortunately, they do not seem to contain the unordered versions.

因此,我想知道将默认STL容器与Boost分配器一起使用是否有问题?也许在不同的平台上?

So, i wonder if there's anything problematic about using the default STL containers with the Boost allocators ? Maybe on a different platform ?

任何提示表示赞赏!

更新:

我想知道它是否在不同的环境中工作,所以我在Coliru上写了一个最小的示例(它惊奇地与std::string一起工作):

I was wondering if it was working in a different environment, so i wrote a minimal example on Coliru (which surprisingly works with std::string):

http://coliru.stacked-crooked.com/a/91d1a143778cf3e9

推荐答案

unordered_map将处理Boost进程间分配器,前提是您的库实现支持有状态分配器¹和使用非原始指针类型的分配器.

unordered_map will cope with Boost Interprocess allocators IFF your library implementation has support for stateful allocators¹ and allocators using non-raw pointer types.

即使如此,就像@rustyx提到的那样,如果您实际上与另一个进程共享内存,您将陷入困境.另一个过程可能是将该段映射到一个不同的基地址,从而使存储在内存区域中的所有指针均无效.

Even so, like @rustyx mentions, you're going to be in deep trouble if you actually share the memory with another process. The other process is likely to map the segment at a different base address, making all pointers stored inside the memory region invalid.

☞您需要也使用带有字符串的进程间分配器!

☞ You need to use a Interprocess allocator with the string too!

这是我通常喜欢写的:

#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

#include <unordered_map>

namespace ipc = boost::interprocess;

namespace Shared {
    using Segment = ipc::managed_shared_memory;
    using Manager = Segment::segment_manager;
    template <typename T> using Alloc = ipc::allocator<T, Manager>;
    template <typename K, typename V, typename KH = std::hash<K>, typename KEq = std::equal_to<K> >
        using HashMap = std::unordered_map<K, V, KH, KEq, Alloc<std::pair<const K, V>> >;

    using String = ipc::basic_string<char, std::char_traits<char>, Alloc<char> >;
}

using OBJ_MAP_TYPE = Shared::HashMap<size_t, Shared::String>;

int main() {
    Shared::Segment msm(ipc::open_or_create, "test", 10ul<<20);

    Shared::Manager* mgr = msm.get_segment_manager();
    OBJ_MAP_TYPE& m = *msm.find_or_construct<OBJ_MAP_TYPE>("aname")(msm.get_segment_manager());

    m.emplace(42, Shared::String("LtUaE", msm.get_segment_manager()));
}

值得注意的细节:

  1. 此位:

  1. This bit:

Shared::Manager* mgr = msm.get_segment_manager();
OBJ_MAP_TYPE& m = *msm.find_or_construct<OBJ_MAP_TYPE>("aname")(mgr);

是执行此操作的便捷捷径

is a convenient short-cut for doing:

Shared::Alloc<OBJ_MAP_TYPE::value_type> alloc_inst(msm.get_segment_manager());
OBJ_MAP_TYPE& m = *msm.find_or_construct<OBJ_MAP_TYPE>("aname")(alloc_inst);

之所以可行,是因为允许从段管理器指针到分配器实例的隐式转换.

This works because the implicit conversion from segment-manager pointer to allocator instance is allowed.

输入MAGIC

您会注意到,嵌套分配器很难使用:

Enter MAGIC

You'll note that the nested allocator is clumsy to work with:

m.emplace(42, Shared::String("LtUaE", msm.get_segment_manager()));

这就是scoped_allocator_adaptor的设计师想要解决的问题.如果将分配器更改为:

That's what the designers of scoped_allocator_adaptor tried to solve. If you change the allocator into:

template <typename T> using Alloc = std::scoped_allocator_adaptor<ipc::allocator<T, Manager> >;

您可以突然写:

m.emplace(42, "LtUaE");

这是因为就地构造是根据用途定义的- 分配器构造(请参见 [allocator.uses.construction] )

This is because in-place construction is defined in terms of uses- allocator construction (see [allocator.uses.construction])

查看 在Coliru上直播

¹准备惊讶,@ SergeyA.我上次检查时Libstdc ++不支持此功能,但自GCC 4.9.0起,它的unordered_map支持它,并且OP似乎有libc ++支持的传闻证据(尽管我们甚至不知道是否存在该实例). typedef:))

¹ prepare to be surprised, @SergeyA. Libstdc++ didn't support this last time I checked, but its unordered_map supports it since GCC 4.9.0, and OP seems to have anecdotal evidence that libc++ does (although we don't even know whether there was ever an instance of the typedef :))

这篇关于共享内存中带有boost :: interprocess分配器的std :: unordered_map-缺点吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆