用boost在共享内存上创建std::string的vetor容器 - 小众知识

用boost在共享内存上创建std::string的vetor容器

2022-08-02 03:49:30 苏内容
  标签: boost/共享/内存
阅读:2815
   //This string is in only in this process (the pointer pointing to the
   //buffer that will hold the text is not in shared memory).
   //But the buffer that will hold "this is my text" is allocated from
   //shared memory
   MyShmString mystring(charallocator);
   mystring = "this is my text";

   //This vector is only in this process (the pointer pointing to the
   //buffer that will hold the MyShmString-s is not in shared memory).
   //But the buffer that will hold 10 MyShmString-s is allocated from
   //shared memory using StringAllocator. Since strings use a shared
   //memory allocator (CharAllocator) the 10 buffers that hold
   //"this is my text" text are also in shared memory.
   MyShmStringVector myvector(stringallocator);
   myvector.insert(myvector.begin(), 10, mystring);

   //This vector is fully constructed in shared memory. All pointers
   //buffers are constructed in the same shared memory segment
   //This vector can be safely accessed from other processes.
   MyShmStringVector *myshmvector =
      shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
   myshmvector->insert(myshmvector->begin(), 10, mystring);

   //Destroy vector. This will free all strings that the vector contains
   shm.destroy_ptr(myshmvector);
   return 0;}

Boost.Interprocess containers support move semantics, which means that the contents of a container can be moved from a container two another one, without any copying. The contents of the source container are transferred to the target container and the source container is left in default-constructed state.

When using containers of containers, we can also use move-semantics to insert objects in the container, avoiding unnecessary copies.

To transfer the contents of a container to another one, use boost::move() function, as shown in the example. For more details about functions supporting move-semantics, see the reference section of Boost.Interprocess containers:

#include <boost/interprocess/managed_shared_memory.hpp>

#include <boost/interprocess/containers/vector.hpp>

#include <boost/interprocess/containers/string.hpp>

#include <boost/interprocess/allocators/allocator.hpp>

#include <cassert>

int main (){

using namespace boost::interprocess; //Typedefs typedef managed_shared_memory::segment_manager SegmentManager; typedef allocator<char, SegmentManager> CharAllocator; typedef basic_string<char, std::char_traits<char> ,CharAllocator> MyShmString; typedef allocator<MyShmString, SegmentManager> StringAllocator; typedef vector<MyShmString, StringAllocator> MyShmStringVector; //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; managed_shared_memory shm(create_only, "MySharedMemory", 10000); //Create allocators CharAllocator charallocator (shm.get_segment_manager()); StringAllocator stringallocator(shm.get_segment_manager()); //Create a vector of strings in shared memory. MyShmStringVector *myshmvector = shm.construct<MyShmStringVector>("myshmvector")(stringallocator); //Insert 50 strings in shared memory. The strings will be allocated //only once and no string copy-constructor will be called when inserting //strings, leading to a great performance. MyShmString string_to_compare(charallocator); string_to_compare = "this is a long, long, long, long, long, long, string..."; myshmvector->reserve(50); for(int i = 0; i < 50; ++i){ MyShmString move_me(string_to_compare); //In the following line, no string copy-constructor will be called. //"move_me"'s contents will be transferred to the string created in //the vector myshmvector->push_back(boost::move(move_me)); //The source string is in default constructed state assert(move_me.empty()); //The newly created string will be equal to the "move_me"'s old contents assert(myshmvector->back() == string_to_compare); } //Now erase a string... myshmvector->pop_back(); //...And insert one in the first position. //No string copy-constructor or assignments will be called, but //move constructors and move-assignments. No memory allocation //function will be called in this operations!! myshmvector->insert(myshmvector->begin(), boost::move(string_to_compare)); //Destroy vector. This will free all strings that the vector contains shm.destroy_ptr(myshmvector); return 0;}

When creating containers of containers, each container needs an allocator. To avoid using several allocators with complex type definitions, we can take advantage of the type erasure provided by void allocators and the ability to implicitly convert void allocators in allocators that allocate other types.

Here we have an example that builds a map in shared memory. Key is a string and the mapped type is a class that stores several 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<int_vector, segment_manager_t>                     int_vector_allocator;

typedef vector<int_vector, int_vector_allocator>                     int_vector_vector;

typedef allocator<char, segment_manager_t>                           char_allocator;

typedef basic_string<char, std::char_traits<char>, char_allocator>   char_string;

class complex_data{

int id_; char_string char_string_; int_vector_vector int_vector_vector_; public: //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(int id, const char *name, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), int_vector_vector_(void_alloc) {}

  //Other members...};

//Definition of the map holding a string as key and complex_data as mapped typet

ypedef std::pair<const char_string, complex_data>                      map_value_type;

typedef std::pair<char_string, complex_data>                            movable_to_map_value_type;

typedef allocator<map_value_type, segment_manager_t>                    map_value_type_allocator;

typedef map< char_string, complex_data

, std::less<char_string>, map_value_type_allocator>          complex_map_type;

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_map_type *mymap = segment.construct<complex_map_type> //(object name), (first ctor parameter, second ctor parameter) ("MyMap")(std::less<char_string>(), alloc_inst); for(int i = 0; i < 100; ++i){ //Both key(string) and value(complex_data) need an allocator in their constructors char_string key_object(alloc_inst); complex_data mapped_object(i, "default_name", alloc_inst); map_value_type value(key_object, mapped_object); //Modify values and insert them in the map mymap->insert(value); } return 0;}


扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1