Boost :: Межпроцессное изменение размера контейнера Нет Конструктора по умолчанию - PullRequest
1 голос
/ 15 апреля 2010

После прохождения документации 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();
        }
    }
}

Это лучший / правильный способ сделать это? Или я что-то упустил.

Спасибо!

...