Boost logo

Boost Users :

Subject: Re: [Boost-users] Mutex synchronised wrapper class for boost::interprocess
From: Riskybiz (riskybizLive_at_[hidden])
Date: 2013-06-25 12:46:04


Ion; thank you!!

 

I found the errors in my prior code thanks to your tip and used the
improvements you suggested. I had unwittingly declared variables with very
similar names and different types, leading to confused behavior. Anyway
that is solved and I now have a working implementation of a mutex
synchronised interprocess vector of strings. Have included it below in case
it's of use to anyone else trying the same...

 

A further question if I may?

 

What is the best approach to extend a managed_shared_memory_segment? I can
dynamically add (via write() function) shared vector elements until such
time as an interprocess_exception boost_interprocess::bad_alloc is thrown;
when the memory allocated to the shared segment is filled. Is there a way
to handle this exception so that the segment can be extended with more
memory and then resume adding data elements to the vector? Or perhaps some
other way to detect the segment memory is running short and take action to
extend it?

 

Thanks again,

 

Riskybiz.

 

Code:

 

Class Definition:

 

#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>

 

#include <iostream>

#include <stdexcept>

 

using namespace boost::interprocess;

 

class SharedMemoryWrapper

{

public:

    SharedMemoryWrapper(const std::string &name, bool server) :
m_name(name), m_server(server)

    {

if (server)

        {

            //Clean up resources from any prior instances

named_mutex::remove("named_mutex");

            shared_memory_object::remove(m_name.c_str());

         

//Create shared memory

m_segment = new managed_shared_memory(create_only, m_name.c_str(),
1000000);

 

//Create allocators

CharAllocator charallocator(m_segment->get_segment_manager());

StringAllocator stringallocator(m_segment->get_segment_manager());

 

//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.

sharedSegmentVector =
m_segment->construct<MyShmStringVector>("sharedSegmentVector")(stringallocat
or);

                   }

        else

        {

            try

{

//Open the shared segment

m_segment = new managed_shared_memory(open_only, name.c_str());

//Find the vector using the c-string name and open it

sharedSegmentVector =
m_segment->find<MyShmStringVector>("sharedSegmentVector").first;

}

catch(interprocess_exception ipe)

{

std::cout << "Error: Interprocess Exception: " << ipe.what() << std::endl;

}

catch(...)

{

std::cout << "Error: Unknown Exception: " << std::endl;

}

        }

                  m_mutex = new named_mutex(open_or_create, "named_mutex");

    }

 

 

    ~SharedMemoryWrapper()

    {

       /*

   //Destructor: Will remove the shared memory resources

   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 instance members

        delete m_mutex;

        delete m_segment;

}

 

    //Writer

void write(const std::string &inStr)

    {

try

{

CharAllocator charallocator(m_segment->get_segment_manager());

scoped_lock<named_mutex> lock(*m_mutex);

MyShmString shmStr(inStr.c_str(), charallocator);

sharedSegmentVector->push_back(shmStr);

}

catch(interprocess_exception ipe)

{

std::cout << "Error in SharedMemoryWrapper::write(): interprocess_exception:
"<< ipe.what() << std::endl;

}

catch(...)

{

std::cout << "Error in SharedMemoryWrapper::write(): unknown error" <<
std::endl;

}

}

 

//Reader

std::string read(size_t &index)

{

try

{

scoped_lock<named_mutex> lock(*m_mutex);

const MyShmString &shmStr = (*sharedSegmentVector)[index];

std::string stdStr(shmStr.begin(), shmStr.end());

return stdStr;

}

catch(interprocess_exception ipe)

{

std::cout << "Error in SharedMemoryWrapper::read(): interprocess_exception:
"<< ipe.what() << std::endl;

}

catch(std::range_error re)

{

std::cout << "Error in SharedMemoryWrapper::read(): range_error: " <<
re.what() << std::endl;

}

catch(...)

{

std::cout << "Error in SharedMemoryWrapper::read(): unknown error "<<
std::endl;

}

return "Error in SharedMemoryWrapper::read()";

}

 

//Vector Size

size_t getSize() const

{

return this->sharedSegmentVector->size();

}

 

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

 

Test Programmes:

 

// PrepareSharedMemoryVectorOfStrings.cpp : Defines the entry point for the
console application.

//

 

#include "SharedMemoryWrapper.h"

#include <iostream>

#include <string>

#include <sstream>

 

int main(int argc, char *argv[])

{

SharedMemoryWrapper *smw = new SharedMemoryWrapper("SharedMemoryTest",
true);

 

size_t cnt(0);

 

while(cnt < 100)

{

//Convert number to string representation

std::string cntStr = static_cast<std::ostringstream*>(
&(std::ostringstream() << cnt) )->str();

//Write to shared memory vector

smw->write("Iteration: " + cntStr);

cnt++;

}

 

size_t vecSize = smw->getSize();

std::cout << "Elements Present: "<< vecSize << std::endl;

 

delete smw;

 

return 0;

}

 

// AccessSharedMemoryVectorOfStrings.cpp : Defines the entry point for the
console application.

//

 

#include "SharedMemoryWrapper.h"

#include <iostream>

#include <string>

 

int main(int argc, char *argv[])

{

SharedMemoryWrapper *smw = new SharedMemoryWrapper("SharedMemoryTest",
false);

 

std::string outStr;

 

for(size_t index = 0; index < 100; index++)

{

outStr = smw->read(index);

std::cout << outStr << std::endl;

}

 

delete smw;

 

return 0;

}

 



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