Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map in Shared memory

I am trying to create an unordered_map in shared memory. I am using allocator to server the purpose.

The code

void *addr;
void *pool;
int shmid;

template<class T>
class MyPoolAlloc {
private:
public:
    typedef size_t     size_type;
    typedef ptrdiff_t  difference_type;
    typedef T*         pointer;
    typedef const T*   const_pointer;
    typedef T&         reference;
    typedef const T&   const_reference;
    typedef T          value_type;

   template<class X>
   struct rebind
   { typedef MyPoolAlloc<X> other; };

   MyPoolAlloc() throw() {
   }
   MyPoolAlloc(const MyPoolAlloc&) throw()  {
   }

   template<class X>
   MyPoolAlloc(const MyPoolAlloc<X>&) throw() {
   }

   ~MyPoolAlloc() throw() {
   }

  pointer address(reference __x) const { return &__x; }

  const_pointer address(const_reference __x) const { return &__x; }

  pointer allocate(size_type __n, const void * hint = 0) {
      pointer tmp = static_cast<T*>(addr);
      addr = (void*)((char*)addr + __n);
      return tmp;
  }

  void deallocate(pointer __p, size_type __n) {
      // pMyPool->Free(reinterpret_cast<void *>(__p));
  }

 size_type max_size() const throw() {
    //return size_t(-1) / sizeof(T);
  }

 void construct(pointer __p, const T& __val) {
     ::new(__p) T(__val);
  }

 void destroy(pointer __p) {
    //__p->~T();
  }
};

typedef std::unordered_map<int, int, std::hash<int>, std::equal_to<int>,  MyPoolAlloc<std::pair<const int,int>> > Map;

int main ()
{
    shmid = shmget(shm_key, 1000, IPC_CREAT | IPC_EXCL | 644);
    if(shmid == -1){
            std::cerr << "Failed to create the shared segment." << strerror(errno)<< std::endl;
            exit(-1);
    }

    addr = shmat(shmid, NULL, 0);
    pool = addr;
    if(addr == (void*)-1){
            std::cerr << "Failed to attach the segment to the process." << std::endl;
            shmctl(shmid, IPC_RMID, 0);
            exit(-1);
    }

    Map *m = new(pool) Map;

    m->insert(std::pair<int, int>(2,4));

    shmdt(addr);
    shmctl(shmid, IPC_RMID, 0);

    return 0;
}

I am allocating memory for the map on shared memory address. And I suppose for the elements the allocator class' allocate() function will be used. But I am not able to figure out how to use allocate function to allocate memory for the elements of the map. I am getting Arithmetic Exception at the line where I am trying to insert in the map.

Could someone please help to understand how the memory layout should be?

Thanks.

like image 484
mandeep Avatar asked Aug 07 '12 08:08

mandeep


1 Answers

As I said last time you asked about this, you can't store pointers in shared memory and expect them to be usable in more than one process. As before, I suggest using boost::unordered_map in conjunction with boost::interprocess::allocator.

If you really want to write your own allocator, you'll need some kind of custom pointer that stores the offset into the shared memory block, and is able to reconstruct the correct address from that. I wouldn't recommend trying to do this yourself: as well as it being quite fiddly, you may find that some implementations of std::unordered_map don't work correctly with unconventional pointer types. In fact, I suspect that it might be impossible to make a standard-compliant allocator for shared memory; otherwise, the Boost allocator would surely be usable by all standard containers, not just special Boost versions.

By the way, you shouldn't use reserved names like __p (containing a double underscore) in your own code; they should only be used by the Standard Library implementation.

like image 195
Mike Seymour Avatar answered Sep 22 '22 07:09

Mike Seymour