在共享内存中分配的映射的映射
Maps of maps allocated in shared memory
在一个boost::interprocess::managed_shared_memory
中,我试图在另一个boost::unordered_map
中创建boost::unordered_map
作为值,两个映射的键都为std::string
。共享内存段内的Map in Map由两个不同的进程访问,从外部&内部贴图。
下面是我的实现&想知道这是可能的/正确的方式还是其他更好的方式?
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_or_create, "BOOST_SHM", 65536);
typedef std::string KeyType;
typedef std::string ValueType;
typedef std::pair<const KeyType, ValueType> MapType;
typedef boost::interprocess::allocator<MapType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
typedef boost::unordered_map<KeyType, ValueType, boost::hash<KeyType>, std::equal_to<KeyType>, ShmemAllocator> InMap;
ShmemAllocator alloc_inst(segment.get_segment_manager());
InMap *inside_map = segment.construct<InMap>("SHM_IN_MAP")(3, boost::hash<KeyType>(), std::equal_to<KeyType>(), alloc_inst);
typedef std::pair<const KeyType, MapType> MIMType;
typedef boost::interprocess::allocator<MIMType, boost::interprocess::managed_shared_memory::segment_manager> MIMShmemAllocator;
typedef boost::unordered_map<KeyType, MapType, boost::hash<KeyType>, std::equal_to<KeyType>, MIMShmemAllocator> OutMap;
//MIMShmemAllocator alloc_inst(segment.get_segment_manager()); /*Commented due to Error*/
OutMap *outside_map = segment.construct<OutMap>("SHM_OUT_MAP")(3, boost::hash<KeyType>(), std::equal_to<KeyType>(), alloc_inst);
其他详细信息:
gcc版本4.8.3 20140911(Red Hat 4.8.3-9)(gcc)在CentOS7上,BOOST _LIB_VERSION"1_58"
好的。
因此,出现了一些基本错误,可能还有一些混乱。
接下来,有一些强大的技巧可以使使用带有自定义(有状态)分配器的嵌套容器更加方便。
以下是工作样本中所有三个提示的汇总,希望能有所帮助!
-
字符串必须也使用共享内存分配器
否则,在另一个进程中使用这些数据将是非法的。使用字符串会导致"未定义的行为"。
至少,让您的字符串使用共享内存分配器:
namespace Shared { using Segment = bip::managed_shared_memory; template <typename T> using Alloc = bip::allocator<T, Segment::segment_manager>; using String = boost::container::basic_string<char, std::char_traits<char>, Alloc<char> >; using KeyType = String; using ValueType = String; }
-
映射分配器指定过多。在映射中封装
pair<K const, v>
元素的实际节点类型无论如何都是实现定义的。那么地图如何知道如何分配这些节点呢?它们重新绑定分配器:请参阅此处文档中的
rebind
所以,你可以通过
Alloc<void>
。或与Shared::String
相同的分配器。地图会发现:typedef boost::unordered_map<KeyType, ValueType, boost::hash<KeyType>, std::equal_to<KeyType>, Alloc<void> > InMap; typedef boost::unordered_map<KeyType, InMap, boost::hash<KeyType>, std::equal_to<KeyType>, Alloc<void> > OutMap;
-
现在查看电源提示。
总是通过有状态的分配器是很烦人的。它把代码搞得一团糟。幸运的是,c++11(以及c++03的Boost Containers)已经涵盖了:
scoped_allocator_adaptor<T...>
allocator_type
uses_allocator<T>
性状
这些帮手可以让你的生活轻松很多。在适用的情况下,它们通过将分配器向下传递给元素类型构造函数来实现这一点。自动地同样,来自反弹分配器类型的隐式转换使事情正常工作。
因此,实际上,您只需构造一个带有正确分配器(使其成为
Scoped
)和一个键的外部映射,就不必一直指定分配器。
这里有一个完整的演示:
在Coliru上直播
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
namespace bip = boost::interprocess;
namespace Shared {
using Segment = bip::managed_shared_memory;
template <typename T>
using Alloc = bip::allocator<T, Segment::segment_manager>;
using Scoped = boost::container::scoped_allocator_adaptor<Alloc<char> >;
using String = boost::container::basic_string<char, std::char_traits<char>, Scoped>;
using KeyType = String;
typedef boost::unordered_map<KeyType, String, boost::hash<KeyType>, std::equal_to<KeyType>, Scoped> InMap;
typedef boost::unordered_map<KeyType, InMap, boost::hash<KeyType>, std::equal_to<KeyType>, Scoped> OutMap;
}
int main() {
srand(time(NULL));
Shared::Segment segment(bip::open_or_create, "BOOST_SHM", 65536);
auto* mgr = segment.get_segment_manager();
Shared::OutMap *p_outside_map = segment.find_or_construct<Shared::OutMap> ("SHM_OUT_MAP") (mgr);
auto& outside_map = *p_outside_map;
Shared::String sskey(mgr); // reduce shared allocations as they are costly (in terms of fragmentation/overhead)
char outer_keys[3], inner_keys[3];
std::generate_n(outer_keys, 3, [] { return rand()%26+'a'; });
std::generate_n(inner_keys, 3, [] { return rand()%26+'a'; });
for (auto key : outer_keys) {
sskey = key;
auto& inner = outside_map[sskey];
for (auto more : inner_keys) {
inner[sskey + "_" + more] += "value";
}
}
for (auto const& oe : outside_map) {
for (auto const& ie : oe.second) {
std::cout << "outside_map[" << oe.first << "][" << ie.first << "] == " << ie.second << "n";
}
}
}
实际上,为了使它在Coliru上工作,我们需要使用一个映射文件:
在Coliru上直播
运行几次:
outside_map[s][s_t] == value
outside_map[s][s_r] == value
outside_map[s][s_c] == value
outside_map[f][f_t] == value
outside_map[f][f_r] == value
outside_map[f][f_c] == value
outside_map[o][o_t] == value
outside_map[o][o_r] == value
outside_map[o][o_c] == value
第二次运行:
outside_map[a][a_d] == value
outside_map[a][a_c] == value
outside_map[a][a_g] == value
outside_map[r][r_d] == value
outside_map[r][r_c] == value
outside_map[r][r_g] == value
outside_map[g][g_d] == value
outside_map[g][g_c] == value
outside_map[g][g_g] == value
outside_map[s][s_t] == value
outside_map[s][s_r] == value
outside_map[s][s_c] == value
outside_map[f][f_t] == value
outside_map[f][f_r] == value
outside_map[f][f_c] == value
outside_map[o][o_t] == value
outside_map[o][o_r] == value
outside_map[o][o_c] == value
请注意每次运行如何成功地将value
附加到3个内部映射中的9个键。
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- C++ 将元素分配给映射值时访问错误
- 包含动态分配内存作为值的映射的取消定位速度有多快?
- 如果可能,标准::映射分配是否静态
- 如何在 OpenCL 中使用缓冲区分配和映射内存机制
- 我如何正确地为std ::映射分配内存
- 我如何将输入分配给在 for 循环中设置的映射功能
- 映射和设置总是一次分配一个项目吗
- 静态映射中动态分配的对象.删除必要的
- C++:通过从映射向量分配映射实例来填充映射的映射
- 映射中的分配最终为0
- C 索引中的字符串映射而无需分配
- 循环访问映射并删除动态分配的元素
- 将无序映射与动态分配的用户定义类一起使用
- STL映射是如何分配的?堆叠或堆
- 任何查找分配给映射的内存大小的方法
- 两个映射之间的分配-移动语义和性能
- c++动态分配(像素映射)
- 标准::移动和映射分配
- C++ std::映射分配错误:无法在赋值中将' type **'转换为'type *'