Создайте вектор строк совместно используемой памяти

Я пытаюсь создать класс, управляющий вектором общей памяти (std) строк.

typedef boost::interprocess::allocator<std::string, boost::interprocess::managed_shared_memory::segment_manager> shmem_allocator;
typedef boost::interprocess::vector<std::string, shmem_allocator> shmem_vector;

shmem_mgr::shmem_mgr() :
shmem_(create_only, SHMEM_KEY, SHMEM_SIZE),
allocator_(shmem_.get_segment_manager())
{
mutex_  = shmem_.find_or_construct<interprocess_mutex>(SHMEM_MUTEX)();
condition_ = shmem_.find_or_construct<interprocess_condition>(SHMEM_CONDITION)();
//buffer_ is of type shmem_vector
buffer_  = shmem_.construct<shmem_vector>(SHMEM_BUFFER_KEY)(allocator_);
}

void shmem_mgr::run() {
running_ = true;

while(running_) {
scoped_lock<interprocess_mutex> lock ( *mutex_ );

int size = buffer_->size();

log_.debug() << size << " queued request(s) found" << std::endl; //LINE 27
for(int i=0; i<size; i++) {
log_.debug() << buffer_->at(i); // at() crashes my app
}

buffer_->clear(); //so does clear()
condition_->wait (lock);
}
}

Клиент успешно добавляет строку в вектор (он также успешно читает эту строку из буфера для отладки), менеджер (код выше) получает сигнал (переменная условия), пишет, что в векторе есть строка (строка 27 ), но когда он пытается получить эту строку через at() приложение вылетает.


Редактировать: Я понял, что использование std::string не возможно, есть string контейнер в boost ipc как раз для этого случая. Это не меняет того факта, что мне нужен вектор (boost / std) строк …


Q: Как я могу передать строки через общую память? Мне нужно сохранить их в некотором буфере (способном хранить> 1 за раз) в shmem, а затем извлечь во втором процессе — это требование. Вход всегда std::string и вывод тоже, но внутреннее представление в shmem может быть другим.

6

Решение

От документы.

#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>

int main ()
{
using namespace boost::interprocess;
//Typedefs
typedef allocator<char, managed_shared_memory::segment_manager>
CharAllocator;
typedef basic_string<char, std::char_traits<char>, CharAllocator>
MyShmString;
typedef allocator<MyShmString, managed_shared_memory::segment_manager>
StringAllocator;
typedef vector<MyShmString, StringAllocator>
MyShmStringVector;

//Open shared memory
//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());

//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;
}
11

Другие решения

вам нужен собственный распределитель для ваших разделяемых классов stl. вам нужен собственный указатель (ACE & Boost имеют эти) определены в распределителе. На противоположных сторонах (CONTIGUOUS) разделяемая память обычно находится по разным адресам. Вам также нужна подсистема выделения разделяемой памяти (менеджер кучи) (из которой выделяется распределитель) — весь нетривиальный низкоуровневый код, но наиболее точно выполнимый, и как только он у вас есть, его можно использовать везде. Если вы сделаете все это, вам нужно только передать смещение (от начала (НЕПРЕРЫВНАЯ !!) области кучи) неплоской структуры вокруг.

Вы можете создавать очереди и все остальное, что вам может понадобиться — все при условии, что «указатели» в объектах основаны на себе и что несмежные кусочки в ваших неплоских кусочках происходят из одной большой смежной фигуры.

Вы не можете использовать std :: string, потому что, если вы не управляете распределением, память в стандартной строке НИЧЕГО не имеет с вашей общей памятью — так же, как и для любой другой структуры stl

Также необходимо (как обычно) решать / согласовывать вопросы владения

1

Вы можете использовать boost :: interprocess :: managed_shared_memory. Следующая программа передает boost :: interprocess :: string между 2 процессами. Отлично работает на моей машине (Ubuntu Linux).
Вы можете использовать managed_shared_memory для передачи векторов или объектов. boost :: interprocess :: string имеет метод c_str ().

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>

int main(int argc, char *argv[])
{
using namespace boost::interprocess;
typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> string;
if(argc == 1){  //Parent process

boost::interprocess::shared_memory_object::remove("MySharedMemory");

//Create a shared memory object.
managed_shared_memory shm (create_only, "MySharedMemory", 1024);

string *s = shm.find_or_construct<string>("String")("Hello!", shm.get_segment_manager());
std::cout << *s << std::endl;

//Launch child process
std::string s1(argv[0]); s1 += " child ";
if(0 != std::system(s1.c_str()))
return 1;
}
else{
//Open already created shared memory object.
managed_shared_memory shm (open_only, "MySharedMemory");
std::pair<string *,std::size_t> ret = shm.find<string>("String");
std::cout << *(ret.first) << std::endl;
}
return 0;
}
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector