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")(stringallocator);

                   }

        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;

}