Search code examples
boostshared-memoryboost-interprocess

How to get boost_ordered_map to work in shared memory


This program give below compiles properly by doing

g++ -o boostwrite boostwrite.cpp -lboost_system -lrt -lm -lpthread

with version g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2

Setting the unordered_map works well but getting the value of it does not work For example on execution of the program

./boostwrite set


write valuebefore crash 1 

test1=0.1

write valuebefore crash 2 

test2=0.2

test1=0.1

write valuebefore crash 3 

test3=0.4

test2=0.2

test1=0.1

But getting returns the size of map as zero

/boostwrite get

mymap address 0x7fb1ca8ad118

reading value

reading valuebefore crash

reading valuebefore crash 0 

I am thinking there are 2 problems here

  1. shared_memory_object::remove("MySharedMemory");

  2. else if(strcmp(argv[1],"get")==0) { mymap = segment.construct("MyHashMap") //object name ( 30, boost::hash(), std::equal_to() //

But I dont know how to fix the problem ?

Any boost experts here to help ?

This program should work like
Header file boostwrite.h

#ifndef BOOSTWRITE_H
#define BOOSTWRITE_H
   #include <boost/interprocess/managed_shared_memory.hpp>
    #include <boost/interprocess/allocators/allocator.hpp>
    #include <boost/interprocess/containers/string.hpp>
    #include <iostream>
    #include <boost/unordered_map.hpp>     //boost::unordered_map
    #include <functional>                  //std::equal_to
    #include <boost/functional/hash.hpp>   //boost::hash


using namespace boost::interprocess;

//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager                       segment_manager_t;
typedef allocator<void, segment_manager_t>                           void_allocator;
typedef allocator<char, segment_manager_t>                           char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator>   char_string;
typedef allocator<int, segment_manager_t>                            int_allocator;
typedef allocator<float, segment_manager_t>                            float_allocator;
typedef float complex_data;

//Definition of the map holding a string as key and complex_data as mapped type
typedef std::pair<const char_string, complex_data>                      map_value_type;
typedef allocator<map_value_type, segment_manager_t>                    map_value_type_allocator;
typedef boost::unordered_map < char_string, complex_data
         , boost::hash<char_string >  ,std::equal_to<char_string >
         , map_value_type_allocator> complex_map_type2;

complex_map_type2 * mymap;

#endif

boostwrite.cpp file

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <iostream>
#include <boost/unordered_map.hpp>     //boost::unordered_map
#include <functional>                  //std::equal_to
#include <boost/functional/hash.hpp>   //boost::hash
#include "boostwrite.h"

managed_shared_memory segment(open_or_create,"MySharedMemory", 65530);
void_allocator alloc_inst (segment.get_segment_manager());
bool insert(string str,float value);
float readfloat(string str);
int main (int argc ,char** argv)
{
    shared_memory_object::remove("MySharedMemory");
//  remove_shared_memory_on_destroy remove_on_destroy("MySharedMemory");

    if(strcmp(argv[1],"set")==0)
    {

        mymap = segment.construct<complex_map_type2>("MyHashMap")  //object name
        ( 30, boost::hash<char_string>(), std::equal_to<char_string>()                  //
        , segment.get_allocator<map_value_type>());                         //allocator instance

        insert("test1",0.1);
        insert("test2",0.2);
        insert("test3",0.4);
    }

    else if(strcmp(argv[1],"get")==0)
    {
          mymap = segment.construct<complex_map_type2>("MyHashMap")  //object name
                ( 30, boost::hash<char_string>(), std::equal_to<char_string>()                  //
                , segment.get_allocator<map_value_type>());  
        printf("mymap address %p \n",mymap);
//      readfloat("test3");
    }
    return 0;
}
bool insert(string str,float value)
{
    {
         char_string key_object(str.c_str(), alloc_inst);
         complex_data mapped_object(value);
         map_value_type value(key_object, mapped_object);
         mymap->insert(value);
    }

    printf("write valuebefore crash %ld \n",mymap->size());
    for(complex_map_type2::iterator i = mymap->begin(); i != mymap->end(); ++i){
        std::cout << i->first << "=" << i->second << std::endl;
      }

}
float readfloat(string str)
{
    printf("reading value\n");
    typedef complex_map_type2::iterator iter;
    char_string key_object(str.c_str(), alloc_inst);

    printf("reading valuebefore crash\n");
    iter got = mymap->find(key_object);
    printf("reading valuebefore crash %ld \n",mymap->size());

}

Solution

  • There are 2 main problems here:

    1. shared memory file is always being removed at program start
    2. "get" part of the program constructs new map

    To address these problems:

    1. remove shared memory file in "set" part of the program just before creating new shared memory file (this will also require moving opennening or creating shared memory file into "set" and "get" parts)
    2. in "get" find already created map

    Your code fixed (your code is a bit of mess - I did not bother to fix other issues like not returning values from functions that require to return, etc.):

    // ......
    // #include's and other code
    // .....
    
    //managed_shared_memory segment(open_or_create,"MySharedMemory", 65530);
    //void_allocator alloc_inst (segment.get_segment_manager());
    bool insert(string str,float value, void_allocator &alloc_inst);
    float readfloat(string str, void_allocator &alloc_inst);
    int main (int argc ,char** argv)
    {
    try
    {
        //shared_memory_object::remove("MySharedMemory");
        //remove_shared_memory_on_destroy remove_on_destroy("MySharedMemory");
    
        if(strcmp(argv[1],"set")==0)
        {
    
            shared_memory_object::remove("MySharedMemory");
            managed_shared_memory segment(open_or_create,"MySharedMemory", 65530);
            void_allocator alloc_inst (segment.get_segment_manager());
            mymap = segment.construct<complex_map_type2>("MyHashMap")  //object name
            ( 30, boost::hash<char_string>(), std::equal_to<char_string>()                  //
            , segment.get_allocator<map_value_type>());                         //allocator instance
    
            insert("test1",0.1, alloc_inst);
            insert("test2",0.2, alloc_inst);
            insert("test3",0.4, alloc_inst);
        }
    
        else if(strcmp(argv[1],"get")==0)
        {
            managed_shared_memory segment(open_or_create,"MySharedMemory", 65530);
            void_allocator alloc_inst (segment.get_segment_manager());
            mymap = segment.find<complex_map_type2>("MyHashMap")  //object name
                     .first;
            printf("mymap address %p \n",mymap);
            readfloat("test3", alloc_inst);
        }
    }
    catch(boost::interprocess::interprocess_exception &e)
    {
        printf("%s\n", e.what());
    }
        return 0;
    }
    bool insert(string str,float value, void_allocator &alloc_inst)
    {
        {
             char_string key_object(str.c_str(), alloc_inst);
             complex_data mapped_object(value);
             map_value_type value(key_object, mapped_object);
             mymap->insert(value);
        }
    
        printf("write valuebefore crash %ld \n",mymap->size());
        for(complex_map_type2::iterator i = mymap->begin(); i != mymap->end(); ++i){
            std::cout << i->first << "=" << i->second << std::endl;
          }
    
    }
    float readfloat(string str, void_allocator &alloc_inst)
    {
        printf("reading value\n");
        typedef complex_map_type2::iterator iter;
        char_string key_object(str.c_str(), alloc_inst);
    
        printf("reading valuebefore crash\n");
        iter got = mymap->find(key_object);
        printf("reading valuebefore crash %ld \n",mymap->size());
        for(complex_map_type2::iterator i = mymap->begin(); i != mymap->end(); ++i){
            std::cout << i->first << "=" << i->second << std::endl;
        }
    }
    

    Output:

    ./boostwrite get
    mymap address 0x7f80a724d118 
    reading value
    reading valuebefore crash
    reading valuebefore crash 3 
    test3=0.4
    test2=0.2
    test1=0.1