共享内存中分配的映射的映射

共享内存中分配的映射的映射

本文介绍了共享内存中分配的映射的映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

boost::interprocess::managed_shared_memory内,我试图在另一个boost::unordered_map内创建boost::unordered_map作为值,两个映射的键都为std::string.共享内存段中Map中的Map通过两个不同的进程进行访问,这两个进程均从外部&内部地图.

Inside a boost::interprocess::managed_shared_memory, I am trying to create boost::unordered_map inside another boost::unordered_map as value, having key as std::string for both maps. This Map in Map inside a shared memory segment gets accessed by two different processes fetch values from both outer & inner maps.

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

Below is my implementation & want to know if this is possible/right way or any other better way possible?

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"

gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) on CentOS 7,BOOST_LIB_VERSION "1_58"

推荐答案

确定.

因此,存在一些基本错误,并且可能有些混乱.

So there were a few basic errors, and possibly some confusion.

接下来,有一些强大的技巧使嵌套容器与自定义(有状态)分配器配合使用更加方便.

Next, there are some power tricks that make using nested containers with custom (stateful) allocators much more convenient.

这是工作示例中所有三个提示的汇总,希望能对您有所帮助!

Here's the roll-up of all three hints in a working sample that hopefully helps!

  1. 您的字符串也必须也使用共享内存分配器

  1. Your strings must use shared memory allocators too

否则,在其他过程中使用该数据将是非法的.使用字符串将导致未定义的行为.

Otherwise the data would be illegal to use in another process. Using the strings would result in Undefined Behaviour.

至少,使您的字符串使用共享内存分配器:

At the very least, make your strings use the shared memory allocator:

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>元素的实际节点类型都是实现定义的.那么地图如何知道如何分配这些节点?

  • The map allocators were overspecified. The actual node-types wrapping the pair<K const, v> elements in a map are implementation defined anyways. So how do maps know how to allocate these nodes?

    它们 重新绑定 分配器:请参见 rebind 在此处的文档中

    They rebind allocators: see rebind in the docs here

    因此,您只需传递Alloc<void>.或与Shared::String相同的分配器.地图将找出答案:

    So, you can just pass Alloc<void>. Or the same allocator as for the Shared::String. The map will figure it out:

    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容器)已经涵盖了:

    Passing stateful allocators all the freaking time is annoying. It makes code a mess. Luckily, c++11 (and Boost Containers for c++03) has you covered:

    • scoped_allocator_adaptor<T...>
    • allocator_type
    • uses_allocator<T>性状
    • scoped_allocator_adaptor<T...>
    • allocator_type
    • uses_allocator<T> trait

    这些助手可以使您的生活更加轻松.他们通过在适用时将分配器向下传递给元素类型构造函数来实现.自动地.再次,反弹分配器类型的隐式转换使事情正常进行.

    These helpers can make your life a lot easier. They do this by passing the allocator down to element type constructors when applicable. Automatically. Again, implicit conversions from rebound allocator types make things work.

    因此,您实际上可以使用正确的分配器(将其设为Scoped)和一个键来构造一个外部映射,并且从那里甚至不必继续指定分配器./p>

  • So, you can actually just construct one outer map with the correct allocator (make it Scoped) and one key, and from there you don't even have to keep specifying allocators.

    这是完整的演示:

    #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上运行,我们需要改用映射文件:

    Actually, to make it work on Coliru, we need to use a mapped file instead:

    运行几次:

    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个键上.

    Note how each run successfully appends value to 9 keys in 3 inner maps.

    这篇关于共享内存中分配的映射的映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-28 06:15