Boost logo

Boost Users :

Subject: [Boost-users] [Interprocess] shared_ptr in shared memory and inheritance
From: Gaetan Gaumer (gaetan.gaumer_at_[hidden])
Date: 2009-02-09 12:26:51


Hello,
we would like to store collections of differents objects derived from a same
base class in a shared
memory segment, and use polymorphism to manipulate them using
shared_ptr<base>.
But as we can't have virtual functions in shared memory we are exploring
this solution :
We designed 2 parallels hierarchies of classes
- A hierarchy of empty objects in process memory with virtual functions
(polymorphism) (ex : class A)
- A hierarchy of data objects in shared memory without virtual functions
(class A_data)

A "process memory" object stores a weak_ptr to the "shared memory" data
object.
Use of data are encapsuled in accessors which take care of weak_ptr locking
and concurrent access.

I don't know if this is a good design (any opinions ?) but it seems to work
well... until the destruction
of "shared memory" objects.
The wrong destructor is used (the base one) instead of the destructor of the
derived class,
probably because the destructor is not virtual...
So I'm currently stuck and I'm looking for some advices.

Here is a little code demonstrating the problem :

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
#include <iostream>
using namespace boost::interprocess;
using namespace std;

class base {
protected :
int id;
public:
base(int i=0):id(i){};
~base(){cout << "base dtor" << endl;}
int getId() const {return id;}
};

class derived : public base {
protected:
double data;
public:
derived(int i=0, double d=0): base(i), data(d){};
~derived(){cout << "derived dtor" << endl;}
double getData(){return data;}
};

typedef managed_shared_ptr<base, fixed_managed_shared_memory>::type
base_shared_ptr;

int main (){
fixed_managed_shared_memory
segment(open_or_create,"sharedPtrSharedMemoryTest", 2048);
// does not compile but that's what I would like
//base_shared_ptr baseSP =
make_managed_shared_ptr(segment.construct<derived>(anonymous_instance)(2,3.0),
segment);
// turnaround
base_shared_ptr baseSP =
make_managed_shared_ptr((base*)segment.construct<derived>(anonymous_instance)(2,3.0),
segment);
    cout << "baseSP->getId() =" << baseSP->getId();
    cout <<", baseSP->getData() = " <<
static_pointer_cast<derived>(baseSP)->getData() << endl;
    baseSP.reset(); // don't know why but base dtor is called 3 times !!!
}

I can live with static_pointer_cast<> because they'll be hidden in
accessors.
But I really need that the right destructor (here ~derived()) will be called
as it's cause some asserts in real case :
include/boost/interprocess/detail/segment_manager_helper.hpp:176: static
boost::interprocess::detail::block_header*
boost::interprocess::detail::block_header::block_header_from_value(const
void*, size_t, size_t): Assertion `hdr->m_value_alignment == algn' failed.

The commented call to make_managed_shared_ptr makes gcc complains with
(thanks gfilt for formatting) :

sharedPtrSharedMemoryTest.cc:30: error: conversion from
   `boost::interprocess::shared_ptr<
        derived
      , boost::interprocess::allocator<
            void
          , boost::interprocess::segment_manager<
                char
              , boost::interprocess::rbtree_best_fit<
                    boost::interprocess::mutex_family, void *, 0u
>, boost::interprocess::iset_index
>
>, boost::interprocess::deleter<
            derived
          , boost::interprocess::segment_manager<
                char
              , boost::interprocess::rbtree_best_fit<
                    boost::interprocess::mutex_family, void *, 0u
>, boost::interprocess::iset_index
> > >' to non-scalar type
   `boost::interprocess::shared_ptr<
        base
      , boost::interprocess::allocator<
            void
          , boost::interprocess::segment_manager<
                char
              , boost::interprocess::rbtree_best_fit<
                    boost::interprocess::mutex_family, void *, 0u
>, boost::interprocess::iset_index
>
>, boost::interprocess::deleter<
            base
          , boost::interprocess::segment_manager<
                char
              , boost::interprocess::rbtree_best_fit<
                    boost::interprocess::mutex_family, void *, 0u
>, boost::interprocess::iset_index
>
>
>' requested

Any help will be welcome.
Gaetan



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