Создание класса с пользовательским распределителем в разделяемой памяти - PullRequest
1 голос
/ 13 марта 2010

Я дергаю себя за волосы из-за следующей проблемы: я следую примеру , приведенному в документации boost.interprocess, чтобы создать экземпляр класса кольцевого буфера фиксированного размера, который я написал в разделяемой памяти. Конструктор скелета для моего класса:

template<typename ItemType, class Allocator >
SharedMemoryBuffer<ItemType, Allocator>::SharedMemoryBuffer( unsigned long capacity ){

    m_capacity = capacity;

    // Create the buffer nodes.
    m_start_ptr = this->allocator->allocate();  // allocate first buffer node
    BufferNode* ptr = m_start_ptr;
    for( int i = 0 ; i < this->capacity()-1; i++ ) {
        BufferNode* p = this->allocator->allocate();    // allocate a buffer node
    }
}

Мой первый вопрос: гарантирует ли этот вид распределения то, что узлы буфера размещаются в смежных областях памяти, то есть, когда я пытаюсь получить доступ к n-му узлу с адреса m_start_ptr + n*sizeof(BufferNode) в моем методе Read(), это будет работать? Если нет, то как лучше сохранить узлы, создав связанный список?

Мой тестовый жгут следующий:

// Define an STL compatible allocator of ints that allocates from the managed_shared_memory.
// This allocator will allow placing containers in the segment
typedef allocator<int, managed_shared_memory::segment_manager>  ShmemAllocator;

//Alias a vector that uses the previous STL-like allocator so that allocates
//its values from the segment
typedef SharedMemoryBuffer<int, ShmemAllocator> MyBuf;

int main(int argc, char *argv[]) 
{
    shared_memory_object::remove("MySharedMemory");

    //Create a new segment with given name and size
    managed_shared_memory segment(create_only, "MySharedMemory", 65536);

    //Initialize shared memory STL-compatible allocator
    const ShmemAllocator alloc_inst (segment.get_segment_manager());

    //Construct a buffer named "MyBuffer" in shared memory with argument alloc_inst
    MyBuf *pBuf = segment.construct<MyBuf>("MyBuffer")(100, alloc_inst);
}

Это дает мне всевозможные ошибки компиляции, связанные с шаблонами для последнего оператора. Что я делаю неправильно? * segment.construct<MyBuf>("MyBuffer")(100, alloc_inst) является правильным способом предоставления двух параметров шаблона?

1 Ответ

1 голос
/ 13 марта 2010

Мой первый вопрос: распределение гарантирует, что буфер узлы расположены в смежных места памяти, т.е. когда я пытаюсь получить доступ к n-му узлу с адреса m_start_ptr + n * sizeof (BufferNode) в мой метод Read () будет работать?

Нет. Причина в том, что у вас есть только первый узел. Все созданные вами BufferNode объекты не сохраняются (скажем, в виде связанных списков) и вызывают утечки памяти. Кроме того, этот стиль распределения не гарантирует смежные области памяти. Произвольный доступ (как вы заявите позже в своем вопросе), скорее всего, потерпит неудачу. Чтобы получить непрерывную память, вам нужно создать массив (возможно динамический) из BufferNode объектов.

Это дает мне всевозможные ошибки компиляции, связанные с шаблонами для последнего оператора. Что я делаю не так?

Трудно сказать, не зная о реальных ошибках. Кроме того, понимаете ли вы свой код (и как вписывается Boost::Interprocess или как работает распределитель)?

Обратите внимание, что в приведенном вами примере создается vector, который гарантированно будет иметь непрерывную память для своих содержащихся объектов. Единственное отличие здесь состоит в том, что объекты создаются в сегменте общей памяти, а не в свободном хранилище, что обычно происходит, когда вы не указываете распределитель в качестве второго параметра и используется по умолчанию.

...