Boost logo

Boost Users :

Subject: [Boost-users] [Interprocess] Using shared Memory with different compilers (msvc, mingw)
From: BaDBuTz (BaDBuTz_at_[hidden])
Date: 2009-10-26 05:06:15


hi,

My library uses boost::interprocess' Shared Memory and has to be delivered with msvc(7.1) and mingw compiled versions.

Every instance of the that library opens a connection to the Shared Memory "sharedMemoryMapTest" and communicates via instances of the class "SyncObject".

In my test program ProcessA opens the shared memory, instanciates a SynObject with the identifyer String "id1". ProcessB connects to the same SyncObject and synchronizes with ProcessA.
If ProcessA and ProcessB are both compiled with the same compiler it works fine. If one process is compiled with mscv and the other is compiled with mingw it fails. (mscv = ProcessA, ProcessB = mingw -> I read my Windows environment variables instead of "id1")

Did I make a mistake in my implementation, or is it simply not possible to access the same Shmem with different compiled versions?

Thanks in advance

Martin

(compilable) code:

#include <iostream>

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/list.hpp>

typedef unsigned long U32;

using namespace boost::interprocess;

class SyncObject
  {
  public:
    SyncObject(std::string aId) : id(aId),
        locAddrSp0Range(0),
        locAddrSp0Remap(0),
        locAddrSp1Range(0),
        locAddrSp1Remap(0),
        usbInterfaceOwner(0),
        useCounter(0)
    {}
    ;

    ~SyncObject()
    {
      std::cout << "SyncObject Destructor\n" << std::flush;
    };

    void print()
    {
      std::cout
      << " id = " << id
      << " locAddrSp0Range = " << locAddrSp0Range
      << " locAddrSp0Remap = " << locAddrSp0Remap
      << " locAddrSp1Range = " << locAddrSp1Range
      << " locAddrSp1Remap = " << locAddrSp1Remap
      << " usbInterfaceOwner = " << usbInterfaceOwner
      << " useCounter = " << useCounter
      << "\n" << std::flush;
    };

    std::string id;

    interprocess_mutex mtxReadWrite;
    interprocess_mutex mtxFunction;

    U32 locAddrSp0Range;
    U32 locAddrSp0Remap;
    U32 locAddrSp1Range;
    U32 locAddrSp1Remap;

    U32 usbInterfaceOwner;

    U32 useCounter;
  };

const char* MANAGED_SHARED_MEMORY_NAME = "sharedMemoryMapTest58";
const char* SYNC_OBJ_LIST_NAME = "sharedMemorySyncList";

typedef offset_ptr<SyncObject> SyncObjOffsetPtr;
typedef allocator<SyncObjOffsetPtr, managed_shared_memory::segment_manager> SyncObjOffsetPtrAllocator;
typedef list<SyncObjOffsetPtr, SyncObjOffsetPtrAllocator> SyncObjectList;

class SharedMemory
  {
  public:
    SharedMemory();
    ~SharedMemory();

    void printList();
    SyncObject* getSyncObject(std::string id);
    void removeSyncObject(std::string id);

  private:
    managed_shared_memory segment;
  };

SharedMemory::SharedMemory()
{
  segment = managed_shared_memory(open_or_create, MANAGED_SHARED_MEMORY_NAME, 65536);
}

SharedMemory::~SharedMemory()
{
  std::cout << "SharedMemory Destuctor\n" << std::flush;

  SyncObjectList* pList = segment.find<SyncObjectList>(SYNC_OBJ_LIST_NAME).first;
  if (pList)
    {
      if (pList->size() < 1)
        {
          segment.destroy_ptr(pList);
          std::cout << "pList destroyed! \n" << std::flush;
        }
    }

  // unlink shared mem object

  // shared_memory_object::remove(MANAGED_SHARED_MEMORY_NAME);

  if( shared_memory_object::remove(MANAGED_SHARED_MEMORY_NAME))
    std::cout << MANAGED_SHARED_MEMORY_NAME << " successfully removed from the system!\n" << std::flush;
  else
    std::cout << MANAGED_SHARED_MEMORY_NAME << " could not be removed from the system!\n" << std::flush;
}

void SharedMemory::printList()
{
  SyncObjectList* pList = segment.find<SyncObjectList>(SYNC_OBJ_LIST_NAME).first;
  if (!pList)
    {
      std::cout << "List does not exist!\n" << std::flush;
      return;
    }

  std::cout << "list contains: ";
  for(SyncObjectList::iterator iter = pList->begin(); iter != pList->end(); ++iter )
    {
      std::cout << iter->get()->id << "\t";
    }

  std::cout << "\n" << std::flush;
}

SyncObject* SharedMemory::getSyncObject(std::string id)
{
  //Initialize shared memory STL-compatible allocator
  const SyncObjOffsetPtrAllocator syncObjOffsetPtrAllocatorInst (segment.get_segment_manager());
  SyncObjectList* pList = segment.find_or_construct<SyncObjectList>(SYNC_OBJ_LIST_NAME)(syncObjOffsetPtrAllocatorInst);

  printList();

  for(SyncObjectList::iterator iter = pList->begin(); iter != pList->end(); ++iter )
    {
      if (iter->get()->id == id)
        {
          std::cout << id << " already exists in SHMem! returning pointer\n";

          iter->get()->useCounter++;
          return iter->get();
        }
    }

  std::cout << id << " is not in the list and will be created in SHMem!\n";

  SyncObject* ptr = segment.construct<SyncObject>(id.c_str())(id);
  ptr->useCounter++;
  pList->push_back(offset_ptr<SyncObject>(ptr));
  return ptr;
}

void SharedMemory::removeSyncObject(std::string id)
{
  //Initialize shared memory STL-compatible allocator
  const SyncObjOffsetPtrAllocator syncObjOffsetPtrAllocatorInst (segment.get_segment_manager());
  SyncObjectList* pList = segment.find_or_construct<SyncObjectList>(SYNC_OBJ_LIST_NAME)(syncObjOffsetPtrAllocatorInst);

  printList();

  for(SyncObjectList::iterator iter = pList->begin(); iter != pList->end(); ++iter )
    {
      if (iter->get()->id == id)
        {
          if (iter->get()->useCounter < 2)
            {
              std::cout << "removing " << id << " from list \n" << std::flush;

              SyncObject *ptr = iter->get();
              segment.destroy_ptr(ptr);
              pList->erase(iter);
            }
          else
            {
              std::cout << "decrementing userCounter of id " << id << "\n" << std::flush;
              iter->get()->useCounter--;
            }
          break;
        }
    }
}

int main()
{
  try
    {
      SharedMemory shm;

      SyncObject *pSync = shm.getSyncObject("id1");
      pSync->mtxFunction.lock();

      pSync->print();
      pSync->locAddrSp0Range++;
      pSync->print();

      pSync->mtxFunction.unlock();
      shm.removeSyncObject("id1");

      pSync = shm.getSyncObject("id1");
      pSync->mtxFunction.lock();

      pSync->print();
      pSync->locAddrSp0Range++;
      pSync->print();

      pSync->mtxFunction.unlock();
      shm.removeSyncObject("id1");

    }
  catch(boost::interprocess::interprocess_exception &ex)
    {
      std::ostringstream sout;
      sout.str("");
      sout << ex.what();

      std::cout << sout.str() << std::flush;
    }
  return 0;
}

-- 
Neu: GMX DSL bis 50.000 kBit/s und 200,- Euro Startguthaben!
http://portal.gmx.net/de/go/dsl02

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