Search code examples
c++templatesboostinterprocessboost-interprocess

Boost template error using inter-process map


EDIT: Although not strictly the the answer I was looking for, that is because I was asking the wrong question. I have marked this question as "answered" because it helped me see what I was doing wrong (when put back in context, the class structure doesn't make sense and needs to be redone differently using similar changes) and I think the poster deserves the rep boost for fixing what is, as he called it, "non-standard."


Please take the time to help with this one. If you're more experienced with Boost than I am, it shouldn't be hard.

I'm using Boost 1.57 to do IPC. I'm trying to make a shared map of pair(void *, struct). Here is an entire program (short). You can plug it into MSVC (or, changing main() declaration and changing it to a regular managed_shared_memory, GCC or Clang).

The code can be found syntax-highlighted at http://pastebin.com/caNNdztt (although I forgot to take out one usage of a #define not present in the code, it is replaced with 0x30000000)

#include <iostream>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_windows_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>


using namespace boost::interprocess;

typedef void* mem_managed_type; // GLE_GLOBAL is just void *, but changing it to int doesn't work
struct global_ptr_state; // This is just a POD struct, the definition doesn't matter

//typedef managed_shared_memory mem_manager_t;
typedef managed_windows_shared_memory mem_manager_t;
typedef std::pair<const mem_managed_type, global_ptr_state> global_state_pair;
typedef mem_manager_t::segment_manager segm_t;
typedef allocator< global_state_pair, segm_t > my_global_allocator;
typedef std::less<mem_managed_type> mem_managed_type_less;
typedef mem_manager_t::segment_manager segm_manager;
typedef map<const mem_managed_type, global_ptr_state, mem_managed_type_less, my_global_allocator> global_ptr_pair_map;

int _tmain(int argc, _TCHAR* argv[])
{
    segm_manager *_segm_manager;
    my_global_allocator *_allocatr;
    global_ptr_pair_map *global_map;
    mem_manager_t managed_pool;

    managed_pool = mem_manager_t(create_only, "thisdoesntmatter", 65536, (void *)0x3C000000);
    shared_memory_object _stator_share(open_only, "thisdoesntmattereither", read_write);
    mapped_region _stator_region(_stator_share, read_write, 0, 0, (void *)0x30000000);
    _segm_manager = managed_pool.get_segment_manager();
    _allocatr = new my_global_allocator(_segm_manager);

    // This line throws the error
    global_map = new global_ptr_pair_map; // This line causes the compilation error
}

The short version of the error is

1>c:\boost\include\boost-1_57\boost\container\map.hpp(493): error C2535: 'std::pair<boost::container::container_detail::iterator<boost::intrusive::tree_iterator<boost::intrusive::bhtraits<T,boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void,ptrdiff_t,size_t,0>,true>,normal_link,boost::intrusive::default_tag,3>,false>,false>,bool> boost::container::map<const mem_managed_type,global_ptr_state,mem_managed_type_less,my_global_allocator,boost::container::tree_assoc_defaults>::insert(const std::pair<const mem_managed_type,global_ptr_state> &)'
: member function already defined or declared

The entire error can be found here on Pastebin

http://pastebin.com/gjk1e1N7

From what I can tell it's complaining about this:

std::pair<iterator,bool> insert(const nonconst_value_type& x)
   { return this->base_t::insert_unique(x); }

replacing this from the statement above in that header:

   std::pair<iterator,bool> insert(const value_type& x)
   { return this->base_t::insert_unique(x); }

I am at my wit's end. Please help!


Solution

  • You need to call construct to create map inside shmem instead of using new, plus few more fixes:

    typedef void* mem_managed_type; // GLE_GLOBAL is just void *, but changing it to int doesn't work
    struct global_ptr_state{}; // This is just a POD struct, the definition doesn't matter
    
    typedef managed_windows_shared_memory mem_manager_t;
    typedef std::pair<const mem_managed_type, global_ptr_state> global_state_pair;
    typedef mem_manager_t::segment_manager segm_t;
    typedef allocator< global_state_pair, segm_t > my_global_allocator;
    typedef std::less<mem_managed_type> mem_managed_type_less;
    typedef mem_manager_t::segment_manager segm_manager;
    typedef map<mem_managed_type, global_ptr_state, mem_managed_type_less, my_global_allocator> global_ptr_pair_map;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        segm_manager *_segm_manager;
        global_ptr_pair_map *global_map;
        mem_manager_t managed_pool;
    
        managed_pool = mem_manager_t(create_only, "thisdoesntmatter", 65536, (void *)0x3C000000);
        shared_memory_object _stator_share(open_only, "thisdoesntmattereither", read_write);
        mapped_region _stator_region(_stator_share, read_write, 0, 0, (void *)0x30000000);
        _segm_manager = managed_pool.get_segment_manager();
        my_global_allocator _allocatr = _segm_manager;
    
        global_map = managed_pool.construct<global_ptr_pair_map>("mymap")(mem_managed_type_less(), _allocatr);
    }
    

    You are doing it in a bit "non-standard" way so I can't tell if that code will work. Why not to follow boost interprocess tutorial?