Использование контейнеров STL для boost::interprocess::managed_shared_memory

Рассмотрим следующую ситуацию:

class Helper
{
    public:
        // Getters and setters are present!
    private:
        int i;
        std::map<int, boost::interprocess::managed_shared_memory> shm;
}

int main()
{
    boost::interprocess::managed_shared_memory shmInfo(boost::interprocess::open_or_create, "Test", 1024);

    boost::interprocess::map<int, Helper> myMap = shmInfo.construct< boost::interprocess::map<int, Helper> >("Memory");
}

myMap (который представляет собой карту int и Helper) построен на общей_памяти. В свою очередь, я хочу, чтобы Helper хранил карту int и boost::interprocess::managed_shared_memory.

Когда я пытаюсь использовать std::map в Helper, я получаю ошибки компилятора:

ошибка C2248: 'boost::interprocess::basic_managed_shared_memory::basic_managed_shared_memory': невозможно получить доступ к частному члену, объявленному в классе 'boost::interprocess::basic_managed_shared_memory'

Как я могу этого добиться?


person CinCout    schedule 13.10.2014    source источник
comment
Попробуйте сделать public Helper участников.   -  person Jepessen    schedule 13.10.2014
comment
У меня есть геттеры/сеттеры для частных переменных!   -  person CinCout    schedule 13.10.2014


Ответы (1)


Хорошо, вот рабочая версия Live On Coliru

Позвольте мне решить некоторые из проблем, которые были в вашем коде:


  1. Начнем сверху

    class Helper
    {
        public:
            // Getters and setters are present!
        private:
            int i;
            std::map<
    -----------^
    
  2. #P4#
    template <typename T> using shm_alloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
    template <typename K, typename V> using shared_map = bip::map<K, V, std::less<K>, shm_alloc<std::pair<K const, V> > >;
    
    #P5#
                      int, boost::interprocess::managed_shared_memory> shm;
    --------------------------------------------^
    
  3. Здесь два момента:

    1. boost::interprocess::managed_shared_memory нельзя скопировать (поскольку он владеет общим ресурсом памяти). В моем примере я использовал shared_ptr<managed_shared_memory>, чтобы обойти это. Вероятно, вы могли бы использовать необработанные указатели, если уверены, что время жизни объектов будет больше, чем у карты, содержащей указатель.

    2. не имеет большого смысла иметь стандартные контейнеры в классе Helper, который живет в разделяемой памяти (std::map будет просто указывать на объекты в локальной куче процесса, что приводит к UB при ссылке из другого процесса). Таким образом, вы должны указать дополнительный межпроцессный распределитель, чтобы поместить элементы контейнера в общую память. По техническим причинам это означает, что вы должны указать компаратор ключей (хотя это просто значение по умолчанию, std::less<K>).

    }
    -^
    
  4. Missing ; :)

    int main()
    {
        boost::interprocess::managed_shared_memory shmInfo(boost::interprocess::open_or_create, "Test", 1024);
    
        boost::interprocess::map
    -------------------------^ 
    
  5. Несмотря на то, что теперь вы используете boost::interprocess::map, вы все равно не указали тип распределителя. Опять же (как и выше), вы можете использовать псевдоним shared_map.

                                <int, Helper> 
    
    -----------------------------------------^ 
    
  6. Отсутствует * для типа результата указателя.

                                              myMap = shmInfo.construct< boost::interprocess::map<int, Helper> >("Memory");
    
    ----------------------------------------------------------------------------------------------------------------------^ 
    
  7. Вы забыли вызвать прокси-объект конструктора.

    }
    
  8. Свободные замечания:

    • you need a constructor in Helper so you can pass the proper allocator instance to the constructor of the shm field
    • использование typedefs (или, в моем примере, псевдонимов шаблонов) действительно делает ваш код более удобным для сопровождения.
    • обратите внимание, что здесь у нас есть два экземпляра распределителя: outer_alloc (для карты помощников) и inner_alloc (для Helper::shm)

Полный рабочий образец

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

namespace bip = boost::interprocess;

using ShMemRef = boost::shared_ptr<bip::managed_shared_memory>;
template <typename T> using shm_alloc = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
template <typename K, typename V> using shared_map = bip::map<K, V, std::less<K>, shm_alloc<std::pair<K const, V> > >;

class Helper
{
  public:
    using inner_alloc = shm_alloc<std::pair<int, ShMemRef>>;
    Helper(inner_alloc const& instance) : shm(instance) {}
  private:
    int i;
    shared_map<int, ShMemRef> shm;
};

int main()
{
    ShMemRef shmInfo = boost::make_shared<bip::managed_shared_memory>(bip::open_or_create, "Main", 1024);

    using outer_alloc = shm_alloc<std::pair<const int, Helper>>;
    outer_alloc oa_instance(shmInfo->get_segment_manager());

    shared_map<int, Helper>* myHelpers = shmInfo->construct<shared_map<int, Helper>>("Memory")(oa_instance);

    Helper::inner_alloc ia_instance(shmInfo->get_segment_manager());
    Helper helper1(ia_instance), helper2(ia_instance), helper3(ia_instance);
    myHelpers->emplace(1, helper1);
    myHelpers->emplace(2, helper2);
    myHelpers->emplace(3, helper3);
}
person sehe    schedule 13.10.2014
comment
Просто добавил 8+ замечаний об исходном коде, чтобы объяснить, что пошло не так/отсутствовало. Надеюсь, это поможет. - person sehe; 14.10.2014