How can I get a string from an extended shared memory vector without triggering a shared memory allocation from the recovered string constructor?

given these types (from here , more or less):

typedef boost::interprocess::managed_shared_memory::segment_manager SegmentManager;
typedef boost::interprocess::allocator<char, SegmentManager> CharAllocator;

typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> ShmString;

typedef boost::interprocess::allocator<ShmString, SegmentManager> StringAllocator;

typedef boost::interprocess::vector<ShmString, StringAllocator> ShmStringVector;

      

Whenever I retrieve the ShmString from ShmStringVector

, the free size of the shared memory segment decreases.

What I think happens whenever it ShmString

is created, even as a stack variable, it allocates space inside the shared memory segment.

When this one ShmString

goes out of scope, memory is returned. But if I'm close to capacity on my segment, I don't want the access to risk causing overruns on the shared memory segment.

How can I get the string without triggering another selection?

In the example below, I tried

//shared mem segment previously created with 1,000,000 bytes allocated
managed_shared_memory segment(open_only, "somename");
CharAllocator charAllocator(segment.get_segment_manager());
ShmStringVector *vec = segment.find<ShmStringVector>("somevectorname").first;

vec->push_back(" ... big string ..."  );       // I can push a const char*
size_t sizeAfterInsertion = segment.get_free_memory();

ShmString   res1 = vec->at(0);  //works, but steals memory from shared memory, at least temporarily !
const char* res2 = vec->at(0);  //compiler error
std::string res3 = vec->at(0);  //compiler error 
size_t sizeAfterGet = segment2.get_free_memory();
size_t diff = sizeAfterInsertion - sizeAfterGet;

      

I proved that memory is taken by declaring ShmString

...

std::string size 170,     
before ins:    999232, after ins: 998976, shared memory taken by ins: 256 
                       after get: 998768, shared memory taken by get: 208

      

+3


source to share


2 answers


As Wug mentions, you can use the link.

Conversion / assignment between string types:

If you really want a copy outside of shared memory, copy it to a regular string (or other allocator):

std::string copied(vec2->at(0).begin(), vec2->at(0).end());

      

Of course, the same works in reverse:

vec2[0].assign(copied.begin(), copied.end());
// Or
vec2->emplace_back({copied.begin(), copied.end()});

      

and etc.

Using Streams Directly in Shared Memory



Note that there is streaming support for Interprocess:

typedef allocator<int, managed_shared_memory::segment_manager>
   IntAllocator;
typedef allocator<char, managed_shared_memory::segment_manager>
   CharAllocator;
typedef vector<int, IntAllocator>   MyVector;
typedef basic_string
   <char, std::char_traits<char>, CharAllocator>   MyString;
typedef basic_vectorstream<MyString>               MyStringStream;

      

Now you can use MyVectorStream

to read / write to shared memory string. This is similar to std::stringstream

, but without having to copy the data to the stream first.

For example, write some data into a vector:

   //Create the stream. To create the internal shared memory
   //basic_string we need to pass the shared memory allocator as
   //a constructor argument
   MyStringStream mystringstream(CharAllocator(segment.get_segment_manager()));

   //Reserve the internal string
   mystringstream.reserve(100*5);

   //Write all vector elements as text in the internal string
   //Data will be directly written in shared memory, because
   //internal string allocator is a shared memory allocator
   for(std::size_t i = 0, max = myvector->size(); i < max; ++i){
      mystringstream << (*myvector)[i] << std::endl;
   }

      

And read it to copy it directly to another shared memory line:

  //Auxiliary vector to compare original data
   MyVector *myvector2 =
      segment.construct<MyVector>("MyVector2")
      (IntAllocator(segment.get_segment_manager()));

   //Avoid reallocations
   myvector2->reserve(100);

   //Extract all values from the internal
   //string directly to a shared memory vector.
   std::istream_iterator<int> it(mystringstream), itend;
   std::copy(it, itend, std::back_inserter(*myvector2));

   //Compare vectors
   assert(std::equal(myvector->begin(), myvector->end(), myvector2->begin()));

      

This is taken from the sample documentation and you can see it [ Live On Coliru] ( http://coliru.stacked-crooked.com/a/7f1f450ac11edd4a

+3


source


Use the link.

ShmString &res1 = vec2->at(0);

      



Remember that this does not actually make a copy of the string, but rather refers to the original string. This is enough for a simple reading of its contents (in which you must declare res1

as const

).

+2


source







All Articles