使用STL容器进行boost :: interprocess :: managed_shared_memory

时间:2014-10-13 14:25:58

标签: c++ boost stdmap boost-interprocess

考虑以下情况:

class Helper
{
    public:
        // Getters and setters are present!
    private:
        int i;
        std::map<int, boost::interprocess::managed_shared_memory> shm;
}

int main()
{
    boost::interprocess::managed_shared_memory shmInfo(boost::interprocess::open_or_create, "Test", 1024);

    boost::interprocess::map<int, Helper> myMap = shmInfo.construct< boost::interprocess::map<int, Helper> >("Memory");
}

myMapintHelper的地图)是在shared_memory上构建的。反过来,我希望Helper能够保存intboost::interprocess::managed_shared_memory的地图。

当我尝试在std::map中使用Helper时,我收到编译错误:

  

错误C2248:   '升压::进程间:: basic_managed_shared_memory :: basic_managed_shared_memory'   :无法访问类中声明的私有成员   '升压::进程间:: basic_managed_shared_memory'

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:2)

好的,这是一个有效的版本 Live On Coliru

让我解决您的代码所遇到的一些问题:


  1. 让我们从顶部开始

    class Helper
    {
        public:
            // Getters and setters are present!
        private:
            int i;
            std::map<
    -----------^
    
  2. 使用std::map对共享内存分配器来说很麻烦,因为它直接在构造函数中进行分配。 boost::container::mapboost::interprocess::map没有,所以在使用Boost进程间分配器时你应该更喜欢它们。使用模板别名,您可以减少声明此类共享地图的复杂性:

      
    template <typename T> using shm_alloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
    template <typename K, typename V> using shared_map = bip::map<K, V, std::less<K>, shm_alloc<std::pair<K const, V> > >;
    
      

    现在你可以&#34;只是&#34;说shared_map<K,V>您之前曾说过的std::map<K,V>

                      int, boost::interprocess::managed_shared_memory> shm;
    --------------------------------------------^
    
  3. 这里有两点:

    1. boost::interprocess::managed_shared_memory不可复制(因为它拥有共享内存资源)。在我的示例中,我使用shared_ptr<managed_shared_memory>来解决此问题。如果您确定对象的生命周期将长于包含指针的地图的生命周期,则可以使用原始指针。

    2. 在共享内存中的Helper类中使用标准分配容器是没有意义的(std :: map将简单地指向进程本地堆上的对象并导致UB从另一个进程引用时)。因此 应该 指定一个boost进程间分配器,以将容器元素放入共享内存中。由于技术原因,这意味着您必须指定关键比较器(事件虽然它只是默认值std::less<K>)。

    3. }
      -^
      
    4. 缺少;:)

      int main()
      {
          boost::interprocess::managed_shared_memory shmInfo(boost::interprocess::open_or_create, "Test", 1024);
      
          boost::interprocess::map
      -------------------------^ 
      
    5. 即使你现在使用boost::interprocess::map,你仍然没有表明分配器类型。再次(如上所述),您可以使用shared_map别名。

                                  <int, Helper> 
      
      -----------------------------------------^ 
      
    6. 指针结果类型缺少*

                                                myMap = shmInfo.construct< boost::interprocess::map<int, Helper> >("Memory");
      
      ----------------------------------------------------------------------------------------------------------------------^ 
      
    7. 您忘记调用构造函数代理对象。

      }
      
    8. 发表评论:

      • 您需要Helper中的构造函数,以便将正确的allocator实例传递给shm字段的构造函数
      • 使用typedef(或在我的示例中,模板别名) 真的 使您的代码更易于维护。
      • 请注意,我们这里有两个分配器实例,outer_alloc(针对助手地图)和inner_alloc(针对Helper::shm

    9. 完整工作样本

      #include <boost/interprocess/managed_shared_memory.hpp>
      #include <boost/interprocess/containers/map.hpp>
      #include <boost/shared_ptr.hpp>
      #include <boost/make_shared.hpp>
      
      namespace bip = boost::interprocess;
      
      using ShMemRef = boost::shared_ptr<bip::managed_shared_memory>;
      template <typename T> using shm_alloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
      template <typename K, typename V> using shared_map = bip::map<K, V, std::less<K>, shm_alloc<std::pair<K const, V> > >;
      
      class Helper
      {
        public:
          using inner_alloc = shm_alloc<std::pair<int, ShMemRef>>;
          Helper(inner_alloc const& instance) : shm(instance) {}
        private:
          int i;
          shared_map<int, ShMemRef> shm;
      };
      
      int main()
      {
          ShMemRef shmInfo = boost::make_shared<bip::managed_shared_memory>(bip::open_or_create, "Main", 1024);
      
          using outer_alloc = shm_alloc<std::pair<const int, Helper>>;
          outer_alloc oa_instance(shmInfo->get_segment_manager());
      
          shared_map<int, Helper>* myHelpers = shmInfo->construct<shared_map<int, Helper>>("Memory")(oa_instance);
      
          Helper::inner_alloc ia_instance(shmInfo->get_segment_manager());
          Helper helper1(ia_instance), helper2(ia_instance), helper3(ia_instance);
          myHelpers->emplace(1, helper1);
          myHelpers->emplace(2, helper2);
          myHelpers->emplace(3, helper3);
      }