Estoy tratando de crear una matriz mapeada (esencialmente una map<int, map<int, int>>) que se almacena en la memoria compartida. Estoy usando boost y siguiendo el ejemplo de esta respuesta: https://stackoverflow.com/a/33913753/5760608

Pero no puedo hacer que esto se compile. Recibo un error muy largo que no puedo analizar.

Compilado usando el siguiente comando: clang -std=c++11 -o shmem_sparse_matrix shmem_sparse_matrix.cpp -lpthread -lrt -lstdc++ -lm

Además, si conoce una implementación de memoria compartida de una matriz de este tipo que pueda usar de inmediato, avíseme: no pude encontrar una.

#include <iostream>
#include <exception>
#include <string>

#include <boost/interprocess/containers/map.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

using namespace boost::interprocess;

static const std::string SHMEM_NAME = "MySharedMemorySegment";

namespace Shared {
    typedef managed_shared_memory                              Segment;
    typedef Segment::segment_manager                           SegmentManager;
    typedef int                                                KeyType;

    template <typename T>
    using Alloc  = allocator<T, SegmentManager>;
    using Scoped = boost::container::scoped_allocator_adaptor<Alloc<int>>;

    typedef map<int, int, Scoped>                              Row;
    typedef map<int, Row, Scoped>                              Matrix;
}

class ShmemTest {
private:
    Shared::Segment *segment;
    Shared::Matrix *matrix;
    size_t shmem_block = 10000;
    struct shm_remove {
        shm_remove()  { shared_memory_object::remove(SHMEM_NAME.data()); }
        ~shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
    } remover;

public:
    ShmemTest() {
        segment = new managed_shared_memory(create_only, SHMEM_NAME.data(), shmem_block);
    }

    void create_matrix() {
        matrix = segment->construct<Shared::Matrix>("SparseMatrix")(segment->get_segment_manager());
    }

    void insert_element(int i, int j, int k) {
        Shared::Row &row = (*matrix)[i];
        row[j] = k;
    }
};

int main() {
    ShmemTest shmem_test;
    shmem_test.create_matrix();
    for (int i = 0; i < 10; ++i) {
        for (int j = 0; j < 10; ++j) {
            shmem_test.insert_element(i, j, i);
        }
    }
}

TLDR de salida del compilador (solo muestra errores):

clang -std=c++11 -o shmem_sparse_matrix shmem_sparse_matrix.cpp -lpthread -lrt -lstdc++ -lm

/usr/local/include/boost/container/detail/tree.hpp:464:14: error: type 'const key_compare' (aka 'const boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >') does not provide a call operator
   {  return this->key_comp()(key1, this->key_from(nonkey2));  }

/usr/local/include/boost/container/detail/tree.hpp:468:14: error: type 'const key_compare' (aka 'const boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >') does not provide a call operator
   {  return this->key_comp()(this->key_from(nonkey1), key2);  }

/usr/local/include/boost/intrusive/detail/tree_value_compare.hpp:98:14: error: type 'const key_compare' (aka 'const boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >') does not provide a call operator
   {  return this->key_comp()(KeyOfValue()(value1), KeyOfValue()(value2));  }

/usr/local/include/boost/container/scoped_allocator.hpp:443:4: error: constructor for 'boost::container::dtl::scoped_allocator_adaptor_base<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >>' must explicitly initialize the base class 'boost::interprocess::allocator<int,
      boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >' which does not have a default constructor
   scoped_allocator_adaptor_base()

shmem_sparse_matrix.cpp:47:37: note: in instantiation of member function 'boost::container::map<int, boost::container::map<int, int, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int,
      boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >, void, void>,
      boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long,
      unsigned long, 0>, 0>, iset_index> > >, void, void>::operator[]' requested here
        Shared::Row &row = (*matrix)[i];

/usr/local/include/boost/container/detail/tree.hpp:464:14: error: type 'const key_compare' (aka 'const boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >') does not provide a call operator
   {  return this->key_comp()(key1, this->key_from(nonkey2));  }

/usr/local/include/boost/container/detail/tree.hpp:468:14: error: type 'const key_compare' (aka 'const boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >') does not provide a call operator
   {  return this->key_comp()(this->key_from(nonkey1), key2);  }

/usr/local/include/boost/intrusive/detail/tree_value_compare.hpp:98:14: error: type 'const key_compare' (aka 'const boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >') does not provide a call operator
   {  return this->key_comp()(KeyOfValue()(value1), KeyOfValue()(value2));  }

shmem_sparse_matrix.cpp:48:12: note: in instantiation of member function 'boost::container::map<int, int, boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<int, boost::interprocess::segment_manager<char,
      boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >, void, void>::operator[]' requested here
        row[j] = k;

Salida completa del compilador: https://gist.github.com/ffrankies/80114b648e9d88c2fd26e361c8b34

1
frankie 5 oct. 2019 a las 21:51

1 respuesta

La mejor respuesta

Necesita definir los typedef correctamente:

typedef managed_shared_memory                              Segment;
typedef Segment::segment_manager                           SegmentManager;
typedef int                                                KeyType;
typedef map<int, int> MappedType;
typedef std::pair<const KeyType, MappedType>               ValueType;

typedef allocator<ValueType, SegmentManager>               ShmemAllocator;

typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> Matrix;

Luego, un pequeño cambio en insert_element() para usar auto: auto &row = (*matrix)[i]; y eso debería funcionar. Ejemplo de trabajo completo a continuación:

#include <iostream>
#include <exception>
#include <string>

#include <boost/interprocess/containers/map.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

using namespace boost::interprocess;

static const std::string SHMEM_NAME = "MySharedMemorySegment";

namespace Shared {
    typedef managed_shared_memory                              Segment;
    typedef Segment::segment_manager                           SegmentManager;
    typedef int                                                KeyType;
    typedef map<int, int> MappedType;
    typedef std::pair<const KeyType, MappedType> ValueType;

    typedef allocator<ValueType, SegmentManager> ShmemAllocator;

    typedef map<KeyType, MappedType, std::less<KeyType>, ShmemAllocator> Matrix;
}

class ShmemTest {
private:
    Shared::Segment *segment;
    Shared::Matrix *matrix;
    size_t shmem_block = 10000;
    struct shm_remove {
        shm_remove()  { shared_memory_object::remove(SHMEM_NAME.data()); }
        ~shm_remove() { shared_memory_object::remove(SHMEM_NAME.data()); }
    } remover;

public:
    ShmemTest() {
        segment = new managed_shared_memory(create_only, SHMEM_NAME.data(), shmem_block);
    }

    void create_matrix() {
        matrix = segment->construct<Shared::Matrix>("SparseMatrix")(segment->get_segment_manager());
    }

    void insert_element(int i, int j, int k) {
        auto &row = (*matrix)[i];
        row[j] = k;
    }
};

int main() {
    ShmemTest shmem_test;
    shmem_test.create_matrix();
    for (int i = 0; i < 10; ++i) {
        for (int j = 0; j < 10; ++j) {
            shmem_test.insert_element(i, j, i);
        }
    }
}
1
doqtor 7 oct. 2019 a las 19:36