在共享内存中分配的地图的地图
Maps of maps allocated in shared memory
在 boost::interprocess::managed_shared_memory
中,我试图在另一个 boost::unordered_map
中创建 boost::unordered_map
作为值,两个映射的键都为 std::string
。共享内存段内 Map 中的这个 Map 被两个不同的进程访问,从外部和内部映射获取值。
下面是我的实现 & 想知道这是 possible/right 方式还是其他更好的方式?
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);
其他详情:
CentOS 7 上的 gcc 版本 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC),
BOOST_LIB_VERSION“1_58”
好的。
所以有一些基本错误,可能还有一些混乱。
接下来,有一些强大的技巧可以使使用带有自定义(有状态)分配器的嵌套容器更加方便。
这是工作示例中所有三个提示的汇总,希望对您有所帮助!
你的字符串也必须使用共享内存分配器
否则数据在另一个进程中使用将是非法的。使用字符串会导致 Undefined Behaviour.
至少,让你的字符串使用共享内存分配器:
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
)和一个键的外部映射,从那里你甚至不需要必须继续指定分配器。
这是一个完整的演示:
#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 上运行,我们需要使用映射文件来代替:
运行它几次:
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 个键。
在 boost::interprocess::managed_shared_memory
中,我试图在另一个 boost::unordered_map
中创建 boost::unordered_map
作为值,两个映射的键都为 std::string
。共享内存段内 Map 中的这个 Map 被两个不同的进程访问,从外部和内部映射获取值。
下面是我的实现 & 想知道这是 possible/right 方式还是其他更好的方式?
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);
其他详情:
CentOS 7 上的 gcc 版本 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC), BOOST_LIB_VERSION“1_58”
好的。
所以有一些基本错误,可能还有一些混乱。
接下来,有一些强大的技巧可以使使用带有自定义(有状态)分配器的嵌套容器更加方便。
这是工作示例中所有三个提示的汇总,希望对您有所帮助!
你的字符串也必须使用共享内存分配器
否则数据在另一个进程中使用将是非法的。使用字符串会导致 Undefined Behaviour.
至少,让你的字符串使用共享内存分配器:
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
)和一个键的外部映射,从那里你甚至不需要必须继续指定分配器。
这是一个完整的演示:
#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 上运行,我们需要使用映射文件来代替:
运行它几次:
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 个键。