C++ 在共享内存中分配的映射的映射

C++ 在共享内存中分配的映射的映射,c++,boost,g++,boost-interprocess,boost-unordered,C++,Boost,G++,Boost Interprocess,Boost Unordered,在一个boost::interprocess::managed_shared_memory中,我试图在另一个boost::unordered_map中创建boost::unordered_map作为值,两个映射都有键asstd::string。共享内存段内的映射中的映射由两个不同的进程访问,从外部映射和内部映射中获取值 下面是我的实现&想知道这是可能的/正确的方法还是其他更好的方法 boost::interprocess::managed_shared_memory segment(boost:

在一个
boost::interprocess::managed_shared_memory
中,我试图在另一个
boost::unordered_map
中创建
boost::unordered_map
作为值,两个映射都有键as
std::string
。共享内存段内的映射中的映射由两个不同的进程访问,从外部映射和内部映射中获取值

下面是我的实现&想知道这是可能的/正确的方法还是其他更好的方法

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);
boost::进程间::托管共享内存段(boost::进程间::打开或创建,“boost\u SHM”,65536);
typedef std::字符串键类型;
typedef std::字符串ValueType;
typedef std::pair MapType;
typedef boost::进程间::分配器ShmemAllocator;
typedef boost::无序映射InMap;
ShmemAllocator alloc_inst(段.get_段管理器());
InMap*inside_map=segment.construct(“SHM_IN_map”)(3,boost::hash(),std::equal_to(),alloc_inst);
typedef std::pair MIMType;
typedef boost::进程间::分配器mimsmallocator;
typedef boost::无序的_映射OutMap;
//MIMHMEMallocator alloc_inst(段.get_段管理器())/*由于错误而注释*/
OutMap*outside_map=segment.construct(“SHM_OUT_map”)(3,boost::hash(),std::equal_to(),alloc_inst);
其他详细信息:

CentOS 7上的gcc版本4.8.3 20140911(Red Hat 4.8.3-9)(gcc), BOOST_LIB_版本“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;
    }
    
  • 现在是电源提示

    总是通过有状态的分配器是令人讨厌的。它把代码弄得一团糟。幸运的是,c++11(以及c++03的Boost容器)已经介绍了:

    • 作用域分配器适配器
    • 分配器类型
    • 使用分配程序
      trait
    这些助手可以让你的生活轻松很多。它们通过将分配器向下传递给元素类型构造函数(如果适用)来实现这一点。自动地同样,来自回弹分配器类型的隐式转换使事情得以进行

    因此,实际上,您可以使用正确的分配器构造一个外部映射(使其
    作用域为
    )和一个键,从那里您甚至不必一直指定分配器

  • 下面是一个完整的演示:

    #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";
            }
        }
    }
    
    第二轮:

    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
    

    请注意,每次运行如何成功地将
    值添加到3个内部映射中的9个键。

    @sehe您好,请详细说明一下,一些指针将非常有用。另外,我不熟悉livecoding.tv/sehe(每次离线显示)当然,我会发布工作结果。很遗憾你看不到这个流,我很高兴创建了这个示例。如果你想查看录制的直播流:(有一些干扰和施工噪音,但你知道……事情发生了:))PS。请注意,
    sskey+“_”+more
    效率很低。最好始终重用相同的
    Shared::String
    实例。您能告诉我这个答案是否对您有帮助吗?在这方面,一些实现对我来说是新的。我需要通过,并把它作为实际项目的要求。那我就可以肯定了。目前,样品运行良好:)嗨,你能告诉我这是否是正确的方法吗?我也很少怀疑“[]”是否在map中重载,以及如何处理两个map中的无效键?@dragonxboth,这正是
    std::string
    正常工作的方式。string对象位于/you/put它所在的位置(在本例中为堆栈本地)。分配器用于分配用于存储字符串值的连续内存(这些都不是共享内存所特有的,您以前可能没有想到)。析构函数做了正确的事情。
    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