Можно ли выделить в личном пространстве памяти объект, созданный для увеличения управляемой общей памяти?

Допустим, я набрал вектор, который будет использоваться для увеличения общей памяти. При его создании я должен передать аллокатор из manage_shared_memory, что имеет смысл.

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

Возможно ли, указав другой распределитель для объекта?

Должен ли я изменить определение моего вектора, чтобы принять обе реализации?

Это невозможно сделать, и поэтому вместо этого я должен использовать другой тип вектора?

Пример кода, который я пытаюсь исправить:

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

using namespace boost::interprocess;

typedef managed_shared_memory::segment_manager SegmentMgr;
typedef allocator<int, SegmentMgr> IntAlloc;
typedef vector<int, IntAlloc> IntVector;

int main()
{
  shared_memory_object::remove("Boost");
  managed_shared_memory managed_shm{ open_or_create, "Boost", 1024 };
  IntAlloc intAlloc = managed_shm.get_segment_manager();
  IntVector vectorInSharedMemory({}, intAlloc);  // <--- this allocates in shared memory
  IntVector vectorInMyOwnPrivateMemorySpace({}, /* ? */); // <--- is there a trick here ?
  return 0;
}

person Norgannon    schedule 20.07.2018    source источник


Ответы (3)


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

Давайте остановимся прямо здесь. Это уже не тот вектор. Учитывая, что распределитель является шаблонным параметром вектора, разные распределители означают разные типы.

Это так же просто, как сказать, что std::vector<int> и std::vector<double> даже не одного типа.

Должен ли я изменить определение моего вектора, чтобы принять обе реализации?

Да, вы можете использовать объявления псевдонимов, чтобы указать, что IntVector является вектором int параметризованного распределителя.

template<typename Alloc> using IntVector=vector<int, Alloc>; // template definition

//    [...]

IntVector<IntAlloc> sharedMemoryVector;
IntVector<std::allocator<int>> localHeapVector;
person UmNyobe    schedule 20.07.2018
comment
Только что понял, что вы можете получить свой пирог и съесть его, заменив управляемый сегмент на managed_external_buffer, которые затем можно поместить куда угодно (в локальную кучу или в (общую) карту памяти). Таким образом, тип может быть идентичным. - person sehe; 20.07.2018

да. Я дал расширенный ответ об этом раньше:

Однако то, что вы называете «частной памятью», является «локальной кучей». Вы также можете сопоставить память с MAP_PRIVATE, что означает что-то еще (см. mmap и, например, Открытие управляемой общей памяти и сопоставленных файлов в режимах "Копировать при записи" или "Только чтение")

person sehe    schedule 20.07.2018
comment
Они показывают то, что описывает другой ответ: добавление распределителя в качестве аргумента шаблона. (Это входит в продвинутую практику, чтобы избежать передачи распределителей при каждом вызове.) - person sehe; 20.07.2018

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

template < typename T >
class switchable_allocator
{
   boost::interprocess::allocator< T, SegmentMgr >* sharedAllocator;
   std::allocator< T > privateAllocator;

public:
   switchable_allocator(boost::interprocess::allocator< T, SegmentMgr >* sharedAllocator) : sharedAllocator(sharedAllocator) {}

   pointer allocate(size_t n)
   {
     if (sharedAllocator)
     {
       return sharedAllocator->allocate(n);
     }
     return privateAllocator.allocate(n);
   }
};
person Alan Birtles    schedule 20.07.2018
comment
Это один подход. Обратите внимание, что создание полиморфных аллокаторов во время выполнения может быть нецелесообразным из соображений производительности. - person sehe; 20.07.2018