После прохождения документации Boost :: Interprocess и поисков в Google, я думаю, я нашел причину / решение этой проблемы. Все, что я нашел, насколько я понимаю, похоже на это намекает, но не выходит и говорит «делай это, потому что ...». Но если кто-нибудь сможет это проверить, я буду признателен.
Я пишу серию классов, которые представляют большой поиск информации, которая хранится в памяти для быстрой производительности в распараллеленном приложении. Из-за размера данных и нескольких процессов, которые выполняются одновременно на одном компьютере, мы используем Boost :: Interprocess для разделяемой памяти, чтобы иметь единственную копию структур.
Я посмотрел документацию и примеры Boost :: Interprocess, и они набирают классы dede для строк совместно используемой памяти, строковых векторов, векторов int и т. Д. И когда они «используют» их в своих примерах, они просто конструируют их, передав распределитель и, возможно, вставить один элемент, который они построили в другом месте. Как и на этой странице: http://www.boost.org/doc/libs/1_42_0/doc/html/interprocess/allocators_containers.html
Итак, следуя их примерам, я создал заголовочный файл с typedefs для классов общей памяти:
namespace shm {
namespace bip = boost::interprocess;
// General/Utility Types
typedef bip::managed_shared_memory::segment_manager segment_manager_t;
typedef bip::allocator<void, segment_manager_t> void_allocator;
// Integer Types
typedef bip::allocator<int, segment_manager_t> int_allocator;
typedef bip::vector<int, int_allocator> int_vector;
// String Types
typedef bip::allocator<char, segment_manager_t> char_allocator;
typedef bip::basic_string<char, std::char_traits<char>, char_allocator> string;
typedef bip::allocator<string, segment_manager_t> string_allocator;
typedef bip::vector<string, string_allocator> string_vector;
typedef bip::allocator<string_vector, segment_manager_t> string_vector_allocator;
typedef bip::vector<string_vector, string_vector_allocator> string_vector_vector;
}
Тогда для одного из моих классов таблиц поиска это определено примерно так:
class Details {
public:
Details(const shm::void_allocator & alloc) :
m_Ids(alloc),
m_Labels(alloc),
m_Values(alloc) {
}
~Details() {}
int Read(BinaryReader & br);
private:
shm::int_vector m_Ids;
shm::string_vector m_Labels;
shm::string_vector_vector m_Values;
};
int Details::Read(BinaryReader & br) {
int num = br.ReadInt();
m_Ids.resize(num);
m_Labels.resize(num);
m_Values.resize(num);
for (int i = 0; i < num; i++) {
m_Ids[i] = br.ReadInt();
m_Labels[i] = br.ReadString().c_str();
int count = br.ReadInt();
m_Value[i].resize(count);
for (int j = 0; j < count; j++) {
m_Value[i][j] = br.ReadString().c_str();
}
}
}
Но когда я его компилирую, я получаю сообщение об ошибке:
'boost::interprocess::allocator<T,SegmentManager>::allocator' : no appropriate default constructor available
И это связано с resize()
вызовами векторных объектов. Поскольку типы allocator
не имеют пустого конструктора (они принимают const segment_manager_t &
), и он пытается создать объект по умолчанию для каждого местоположения. Поэтому, чтобы он работал, я должен получить объект-распределитель и передать объект значения по умолчанию на resize
. Как это:
int Details::Read(BinaryReader & br) {
shm::void_allocator alloc(m_Ids.get_allocator());
int num = br.ReadInt();
m_Ids.resize(num);
m_Labels.resize(num, shm::string(alloc));
m_Values.resize(num, shm::string_vector(alloc));
for (int i = 0; i < num; i++) {
m_Ids[i] = br.ReadInt();
m_Labels[i] = br.ReadString().c_str();
int count = br.ReadInt();
m_Value[i].resize(count, shm::string(alloc));
for (int j = 0; j < count; j++) {
m_Value[i][j] = br.ReadString().c_str();
}
}
}
Это лучший / правильный способ сделать это? Или я что-то упустил.
Спасибо!