【问题标题】:How to I create a boost interprocess vector of interprocess containers?如何创建进程间容器的 boost 进程间向量?
【发布时间】:2014-12-04 11:30:17
【问题描述】:

我喜欢创建一个包含进程间容器的类的 boost 进程间向量。 以下代码在 resize 函数调用之前有效,当然因为我的类没有默认构造函数。 我该如何解决这个问题? 示例基于boostContainers of containers示例

谢谢 马库斯

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

using namespace boost::interprocess;

//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager                       segment_manager_t;
typedef allocator<void, segment_manager_t>                           void_allocator;
typedef allocator<int, segment_manager_t>                            int_allocator;
typedef vector<int, int_allocator>                                   int_vector;
typedef allocator<char, segment_manager_t>                           char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator>   char_string;

class complex_data
{
public:
   int               id_;
   char_string       char_string_;
   int_vector int_vector_;

   //Since void_allocator is convertible to any other allocator<T>, we can simplify
   //the initialization taking just one allocator for all inner containers.
   complex_data(const void_allocator &void_alloc)
      : id_(-1), char_string_(void_alloc), int_vector_(void_alloc)
   {}
   //Other members...
};


typedef allocator<complex_data, segment_manager_t>     complex_data_allocator;
typedef vector<complex_data, complex_data_allocator>   complex_data_vector;

int main ()
{
   //Remove shared memory on construction and destruction
   struct shm_remove
   {
      shm_remove() { shared_memory_object::remove("MySharedMemory"); }
      ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
   } remover;

   //Create shared memory
   managed_shared_memory segment(create_only,"MySharedMemory", 65536);

   //An allocator convertible to any allocator<T, segment_manager_t> type
   void_allocator alloc_inst (segment.get_segment_manager());

   //Construct the shared memory map and fill it
   complex_data *complex_data0_ = segment.construct<complex_data> ("MyCompexData")(alloc_inst);

   complex_data0_->char_string_ = "Hello Wold";
   complex_data0_->int_vector_.push_back(3);

   complex_data *complex_data1_ = segment.find_or_construct<complex_data> ("MyCompexData")(alloc_inst);
   complex_data1_->int_vector_.push_back(6);

   std::cout << complex_data1_->id_ << ", " << complex_data0_->char_string_;
   for(size_t i = 0; i < complex_data1_->int_vector_.size(); i++) std::cout << ", " << complex_data1_->int_vector_[i];


   complex_data_vector *complex_data_vector0 = segment.construct<complex_data_vector> ("MyCompexDataVector")(alloc_inst);

   /**
    * Problem
    * How to I resize or add new elements?
    **/
   complex_data_vector0->resize(3);  


   return 0;
}

【问题讨论】:

    标签: boost vector containers interprocess allocator


    【解决方案1】:

    重写

    由于 Boost 容器支持作用域分配器模式,您可以只使用作用域分配器,当该元素具有专门针对的 uses_allocator&lt;&gt; trait它:

    Live On Coliru

    #include <boost/interprocess/managed_shared_memory.hpp>
    #include <boost/container/scoped_allocator.hpp>
    #include <boost/interprocess/allocators/allocator.hpp>
    #include <boost/interprocess/containers/map.hpp>
    #include <boost/interprocess/containers/vector.hpp>
    #include <boost/interprocess/containers/string.hpp>
    
    using namespace boost::interprocess;
    
    //Typedefs of allocators and containers
    typedef managed_shared_memory::segment_manager                       segment_manager_t;
    typedef boost::container::scoped_allocator_adaptor<allocator<void, segment_manager_t> >
                                                                         void_allocator;
    typedef void_allocator::rebind<int>::other                           int_allocator;
    typedef vector<int, int_allocator>                                   int_vector;
    
    typedef void_allocator::rebind<char>::other                          char_allocator;
    typedef basic_string<char, std::char_traits<char>, char_allocator>   char_string;
    
    class complex_data
    {
    public:
       int               id_;
       char_string       char_string_;
       int_vector int_vector_;
    
       //Since void_allocator is convertible to any other allocator<T>, we can simplify
       //the initialization taking just one allocator for all inner containers.
       typedef void_allocator allocator_type;
    
       complex_data(complex_data const& other, const allocator_type &void_alloc)
           : id_(other.id_), char_string_(other.char_string_, void_alloc), int_vector_(other.int_vector_, void_alloc)
       {}
       complex_data(const allocator_type &void_alloc)
          : id_(-1), char_string_(void_alloc), int_vector_(void_alloc)
       {}
       //Other members...
       //
    };
    
    typedef void_allocator::rebind<complex_data>::other    complex_data_allocator;
    typedef vector<complex_data, complex_data_allocator>   complex_data_vector;
    
    int main ()
    {
       //Remove shared memory on construction and destruction
       struct shm_remove
       {
          shm_remove() { shared_memory_object::remove("MySharedMemory"); }
          ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
       } remover;
    
       //Create shared memory
       managed_shared_memory segment(create_only,"MySharedMemory", 65536);
    
       //An allocator convertible to any allocator<T, segment_manager_t> type
       void_allocator alloc_inst (segment.get_segment_manager());
    
       //Construct the shared memory map and fill it
       complex_data *complex_data0_ = segment.construct<complex_data> ("MyCompexData")(alloc_inst);
    
       complex_data0_->char_string_ = "Hello Wold";
       complex_data0_->int_vector_.push_back(3);
    
       complex_data *complex_data1_ = segment.find_or_construct<complex_data> ("MyCompexData")(alloc_inst);
       complex_data1_->int_vector_.push_back(6);
    
       std::cout << complex_data1_->id_ << ", " << complex_data0_->char_string_;
       for(size_t i = 0; i < complex_data1_->int_vector_.size(); i++) std::cout << ", " << complex_data1_->int_vector_[i];
    
    
       complex_data_vector *complex_data_vector0 = segment.construct<complex_data_vector> ("MyCompexDataVector")(alloc_inst);
    
       complex_data_vector0->resize(3);
       complex_data_vector0->emplace_back();
    }
    

    请注意我如何使分配器定义重新绑定void_allocator 类型,从而更容易更改代码的“根分配器”实现。

    【讨论】:

    • 感谢您的建议,但它不起作用。我按照您的建议尝试了插入。 /usr/include/c++/4.8/bits/stl_algobase.h:739:11:错误:'operator='不匹配(操作数类型为'complex_data'和'const complex_data')跨度>
    • 这意味着您的元素类型 (complex_data) 不可复制/可移动。见这里:T must meet the requirements of CopyAssignable and CopyConstructible.
    • 这正是我的观点,我建议的课程如何解决这个问题?
    • @moresun 好吧,我有时间在 GCC 机器上查看了这个,这里列出了所有的方法Live On Coliru。如果您的complex_data 与您的问题代码不同,则解决方案使其可复制!参见例如Rule Of Three。如果您在此过程中遇到困难,您可以发布有关该问题的问题
    • @moresun 想一想:您需要以某种方式将分配器实例提供给元素类型的构造函数。因此,你不能。除非您对分配器实例进行全局引用(这将是一个非常糟糕的主意)。
    猜你喜欢
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    相关资源
    最近更新 更多