Boost logo

Boost Users :

Subject: Re: [Boost-users] Mutex synchronised wrapper class for boost::interprocess shared memory vector of strings
From: Riskybiz (riskybizLive_at_[hidden])
Date: 2013-06-19 17:10:26


Date: Wed, 19 Jun 2013 22:05:32 +0200
From: Ion Gazta?aga <igaztanaga_at_[hidden]>
To: boost-users_at_[hidden]
Subject: Re: [Boost-users] Mutex synchronised wrapper class for
        boost::interprocess shared memory vector of strings
Message-ID: <51C20F0C.8090408_at_[hidden]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

El 18/06/2013 16:28, Riskybiz escribi?:
> I'm trying to write a wrapper class in C++ to give mutex synchronised
> interprocess access to a shared memory vector of strings. This is my first
> foray into boost::interprocess and allocators are proving something of a
> mystery.
>
> Is anyone able to see why on compilation I get the error:

When you build any container in shared memory it must be constructed
with an allocator. Change your push function to (not charallocator is
passed to MyShmString):

void push(const std::string & in)
{
     CharAllocator charallocator(m_segment->get_segment_manager());
     scoped_lock<named_mutex> lock(*m_mutex);
     MyShmString inStr(in.c_str(), charallocator);
     sharedSegmentVector->push_back(inStr);
}

Best,

Ion

Thanks for the reply Ion.

I'm now having trouble reading from the vector in the shared memory. I get
an exception when calling read(0) or read(1). What I'm trying to do is read
"testing testing 123" from the first element of the sharedSegmentVector.
Is it necessary to use some particular type conversion technique in the
reader function to access a sharedSegmentVector string element? Any help to
get this working is much appreciated; I've been trying for more than a month
to get to this point! Code below.....

Thanks

Riskybiz

#ifndef SHARED_MEMORY_WRAPPER_H//if not defined already
#define SHARED_MEMORY_WRAPPER_H//then define it

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>

using namespace boost::interprocess;

class SharedMemoryWrapper
{
public:
    SharedMemoryWrapper(const std::string &name, bool server) :
m_name(name), m_server(server)
    {
                if (server)
        {
            named_mutex::remove("named_mutex");
            shared_memory_object::remove(m_name.c_str());
         
                        //Create shared memory
                        managed_shared_memory m_segment(create_only,
m_name.c_str(), 10000);
            
                        //Create allocators
                        CharAllocator
charallocator(m_segment.get_segment_manager());
                        StringAllocator
stringallocator(m_segment.get_segment_manager());
                        
                        //This string is in only in this process (the
pointer pointing to the
                        //buffer that will hold the text is not in shared
memory).
                        //But the buffer that will hold "this is my text" is
allocated from
                        //shared memory
                        MyShmString mystring(charallocator);
                        mystring = "testing testing 1 2 3";

                        //This vector is fully constructed in shared memory.
All pointers
                        //buffers are constructed in the same shared memory
segment
                        //This vector can be safely accessed from other
processes.
                        MyShmStringVector *sharedSegmentVector =
m_segment.construct<MyShmStringVector>("sharedSegmentVector")(stringallocato
r);
   
                        sharedSegmentVector->push_back(mystring);
                }
        else
        {
            //Open the shared segment
                        managed_shared_memory m_segment(open_only,
name.c_str());
            //Find the vector using the c-string name and open it
                        MyShmStringVector *sharedSegmentVector =
m_segment.find<MyShmStringVector>("sharedSegmentVector").first;
        }
        m_mutex = new named_mutex(open_or_create, "named_mutex");
    }

    ~SharedMemoryWrapper()
    {
        if (m_server)
        {
            named_mutex::remove("named_mutex");
                        
                        //Destroy the vector from the managed_shared_memory
                        m_segment->destroy_ptr(sharedSegmentVector);//This
will free all strings that the vector contains
        
m_segment->destroy<MyShmStringVector>("sharedSegmentVector");//Destroy the
vector
                        
                        //Is it necessary to destroy the allocators here?
                        
                        //Remove the managed_shared_memory; this may fail if
the memory does not exist or is mapped or opened by another process
                        shared_memory_object::remove(m_name.c_str());
                
                }
        delete m_mutex;
        delete m_segment;
        }

    //Writer
        void write(const std::string &in)
    {
     CharAllocator charallocator(m_segment->get_segment_manager());
     scoped_lock<named_mutex> lock(*m_mutex);
     MyShmString shmStr(in.c_str(), charallocator);
     sharedSegmentVector->push_back(shmStr);
    }
    

        //Reader
        std::string read(long index)
        {
                CharAllocator
charallocator(m_segment->get_segment_manager());
                scoped_lock<named_mutex> lock(*m_mutex);
                MyShmString shmStr(sharedSegmentVector->at(index),
charallocator);
                std::string stdStr = std::string(shmStr.begin(),
shmStr.end());
                return stdStr;
        }

private:
    //Typedefs
        typedef boost::interprocess::allocator<char,
managed_shared_memory::segment_manager> CharAllocator;
        typedef boost::interprocess::basic_string<char,
std::char_traits<char>, CharAllocator> MyShmString;
        typedef boost::interprocess::allocator<MyShmString,
managed_shared_memory::segment_manager> StringAllocator;
        typedef boost::interprocess::vector<MyShmString, StringAllocator>
MyShmStringVector;
        
        bool m_server;
    std::string m_name;

        managed_shared_memory *m_segment;
    MyShmStringVector *sharedSegmentVector;
        named_mutex *m_mutex;
};//class
#endif//header guard


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net