Boost logo

Boost Users :

Subject: Re: [Boost-users] Boost Shared Memory Compilation Issue
From: Nathan Lewis (nathanlewissubscription_at_[hidden])
Date: 2011-07-27 12:17:43


TONGARI <tongari95 <at> gmail.com> writes:

>
> Define yourcomplex_data& operator=(complex_data const& other) I have no idea
why compiler cannot generate this assignment operator which accepts const&,
maybe it's because of the move emulation used by interprocess containers?
>

I am wondering if it is because there was internal vectors. So I defined one and
tested it in both applications using the shared memory and it seems to work. I
defined it as below. Not sure if I really needed to loop over the vector in
(rhs) or not was there a cleaner way to do this? It also just felt weird writing
one, I am guessing it is really just updating pointers in shared memory?

complex_data& operator=(const complex_data &rhs)
{
   this->id_ = rhs.id_;
   this->char_string_ = rhs.char_string_;
   this->price_ = rhs.price_;
   char_string_vector_constiterator it = rhs.char_string_vector_vector_.begin();
   while (it != rhs.char_string_vector_vector_.end())
   {
      this->char_string_vector_vector_.push_back(*it);
      it++;
   }
   return(*this);
}

Also I am now focusing on destructing the object I take out of the vector in the
application where I want to read what is put in. I realize that care must be
taken when adding/deleting from the vector in two sample applications and think
I know what I need to do for that. Also know that deleting from vectors isn't
the most efficient way. But as far as the syntax of deleting an object from the
vector which both reside in shared memory.

I don't believe that pop_back deletes the object that's popped so am looking to
firm up for sure how I'd delete one. Looking at the vast examples in the
interprocess documentation it appears that one uses segment.destroy for objects
that were created in shared memory with segment.construct, such as my vector of
complex_data objects; and that for allocations of objects such as in the boost
example at the bottom that are created by allocating segment.allocate the object
in shared memory one uses segment.deallocate(object) call.

However for objects that I've inserted into my vector in the code below, do I
also need to call this deallocate method. I've tried it and it doesn't crash. I
am looking to get some affirmation on this approach as I don't want to be
creating a memory leak in shared memory. Here is the line where I allocated the
object and put it in the vector:
complex_data myItem(7, "hi", 7.0, alloc_inst);
myItem.addStringItem("hello");
myItem.addStringItem("how");
myItem.addStringItem("are");
myItem.addStringItem("you");

myComplexDataVector->push_back(myItem);

Here is how I think I should delete:
segment.deallocate(&myItem);

Below is the complete source example
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>

using namespace boost::interprocess;
using std::cout;
using std::endl;

//Typedefs of allocators and containers
typedef managed_shared_memory::segment_manager segment_manager_t;
typedef allocator<void, segment_manager_t> void_allocator;
typedef allocator<int, segment_manager_t> int_allocator;
typedef vector<int, int_allocator> int_vector;
typedef allocator<int_vector, segment_manager_t>int_vector_allocator;
typedef vector<int_vector, int_vector_allocator>int_vector_vector;
typedef allocator<char, segment_manager_t> char_allocator;
typedef basic_string<char, std::char_traits<char>, char_allocator>char_string;
typedef allocator<char_string, segment_manager_t>char_string_allocator;
typedef vector<char_string, char_string_allocator>char_string_vector_vector;
typedef char_string_vector_vector::iterator char_string_vector_iterator;
typedef char_string_vector_vector::const_iterator
char_string_vector_constiterator;

class complex_data
{
  public: //Obviously making the variables of complex_data public isn't a good
idea I am just playing here for the moment
  int id_;
  char_string char_string_;
  char_string_vector_vector char_string_vector_vector_;
  double price_;
  //Since void_allocator is convertible to any other allocator<T>, we simplify
  //the initialization taking just one allocator for all inner containers.
  complex_data(int id, const char *name, double prce, const void_allocator
&void_alloc) : id_(id), char_string_(name, void_alloc),
char_string_vector_vector_(void_alloc), price_(prce)
  {}

  complex_data& operator=(const complex_data &rhs)
  {
    this->id_ = rhs.id_;
    this->char_string_ = rhs.char_string_;
    this->price_ = rhs.price_;
    char_string_vector_constiterator it = rhs.char_string_vector_vector_.begin();
    while (it != rhs.char_string_vector_vector_.end())
    {
      this->char_string_vector_vector_.push_back(*it);
      it++;
    }
    return(*this);
  }

  void addStringItem(const char* s)
  {
    //Every time you build from a raw string you need an allocator
    //in the constructor
    char_allocator alloc(char_string_vector_vector_.get_allocator());
    char_string_vector_vector_.push_back(char_string(s, alloc));
  }
};

typedef allocator<complex_data, segment_manager_t> ShmemExchangeDataAllocator;
typedef vector<complex_data, ShmemExchangeDataAllocator> ComplexDataVector;

int main ()
{
  //Remove shared memory on construction and destruction
  struct shm_remove
  {
    shm_remove() { shared_memory_object::remove("MySharedMemory"); }
    ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
  } remover;

  //Create shared memory
  managed_shared_memory segment(create_only,"MySharedMemory", 65536);

  //An allocator convertible to any allocator<T, segment_manager_t> type
  void_allocator alloc_inst(segment.get_segment_manager());

  ComplexDataVector* myComplexDataVector =
                        segment.construct<ComplexDataVector>
                          ("ComplexDataVector")(alloc_inst);

  complex_data myItem(7, "hi", 7.0, alloc_inst);
  myItem.addStringItem("hello");
  myItem.addStringItem("how");
  myItem.addStringItem("are");
  myItem.addStringItem("you");

  myComplexDataVector->push_back(myItem);

  complex_data* myCD = &myComplexDataVector->back();
  cout << "Complex Data is: id = " << myCD->id_ << ", char_string_ = " <<
myCD->char_string_ << ", price = " << myCD->price_ << endl;

  char_string_vector_iterator it =
                     myCD->char_string_vector_vector_.begin();
  while (it != myCD->char_string_vector_vector_.end())
  {
    cout << "Inserted String is: " << *it << endl;
    it++;
    //cout << "Something" << endl;
  }

  // remove the item from the vector
  myComplexDataVector->pop_back();

  //Deallocate previously allocated memory
  segment.deallocate(myCD);

  return 0;
}

referenced boost example using both allocate and deallocate:
int main ()
{
   //Remove shared memory on construction and destruction
   struct shm_remove
   {
      shm_remove() { shared_memory_object::remove("MySharedMemory"); }
      ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
   } remover;

   //Create shared memory
   managed_shared_memory segment(create_only,
                                 "MySharedMemory", //segment name
                                 65536);

   //Create linked list with 10 nodes in shared memory
   offset_ptr<list_node> prev = 0, current, first;

   int i;
   for(i = 0; i < 10; ++i, prev = current){
      current = static_cast<list_node*>(segment.allocate(sizeof(list_node)));
      current->value = i;
      current->next = 0;

      if(!prev)
         first = current;
      else
         prev->next = current;
   }

   //Communicate list to other processes
   //. . .
   //When done, destroy list
   for(current = first; current; /**/){
      prev = current;
      current = current->next;
      segment.deallocate(prev.get());
   }
   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