
Hi Ion, Some of my students tried to use boost::circular_buffer with Boost.Interprocess allocators. Apparently the docs does not mention circular_buffer as one that is compatible with Boost.Interproccess. What do we need to do to make a container that support the special allocators? In particular, if I want to use boost::ptr_vector, then do I need to have stateful allocators (both the normal container allocator, and the clone_allocator)? Thanks -Thorsten

Thorsten Ottosen wrote:
Hi Ion,
Some of my students tried to use boost::circular_buffer with Boost.Interprocess allocators. Apparently the docs does not mention circular_buffer as one that is compatible with Boost.Interproccess.
I had never tested this and I've just tried to do an small example that does not compile.
What do we need to do to make a container that support the special allocators?
Change the code to avoid assuming allocator::pointer is T*. This is usually easy but tedious (replace raw pointer declarations with typedefs that come from the allocator, change some calls that need raw pointers (ptr), with "&*ptr" and similar...). The easiest way is to instantiate the container with a shared memory allocator and start "fixing" code....
In particular, if I want to use boost::ptr_vector, then do I need to have stateful allocators (both the normal container allocator, and the clone_allocator)?
Sorry, I'm not familiar with ptr_containers. If you can give me some hints on what's clone_allocator for, I'll be glad to help you to make ptr_container compatible with shared memory allocators. Just one issue: shared memory does not support virtual functions, so I don't think polymorphic cloning will be usable at all. Joaquín has successfully changed multiindex code to support Interprocess so maybe he knows better than anyone what's the best way to make an existing container compatible with Interprocess. For std-like containers changing pointer declarations and replacing some calls was enough. Regards, Ion

Ion Gaztañaga wrote:
Thorsten Ottosen wrote:
What do we need to do to make a container that support the special allocators?
[...] Joaquín has successfully changed multiindex code to support Interprocess so maybe he knows better than anyone what's the best way to make an existing container compatible with Interprocess.
My adaptation process allows for special allocators to have the following relaxations with respect to the standard (which implicitly includes allocators from Boost.Interprocess): "For every type T, the type Allocator::rebind<T>::other::pointer can be any kind of Random Access Iterator, provided that it is explicitly constructible from the literal 0 (standing here as the null pointer) or from any p of type T* pointing into an area allocated by some instance of Allocator or some other allocator type rebound from Allocator. A pointer constructed from p shall dereference to *p." The former allows us to apply the following idiom: Allocator::rebind<T>::other::pointer p1=...; T* p2=&*p1; p2 and p1 point to the same T object and in general are interchangeable (I can construct an Allocator::rebind<T>::other::pointer from a T*). This leads to a particularly simple rule when adapting a container to these special allocators: Replace a T* p with a Allocator::rebind<T>::other::pointer *only if* p is a non-local variable. Otherwise (i.e. p is a local or automatic variable) just leave it like that and use the p2=&*p1 idiom if necessary. The rationale is that local pointers won't ever live in shared memory so it's not necessary to have them replaced by special pointes. This makes the adaptation process a little simpler. This process can be summarized as: 1. Replace (for adaptation purposes) your good old standard allocator with a special allocator such as that in https://svn.boost.org/trac/boost/browser/trunk/libs/multi_index/test/non_std... This will result in lots of compilation errors. 2. Look for all persistent (non-local) variables of type T* and re-type to Allocator::rebind<T>::other::pointer. This will result in further compilation errors due to the impedance between Allocator::rebind<T>::other::pointer's and the remaining T *'s. 3. Locate the points of impedance mismatch referred to above and adapt using the p2=&*p1 idiom. The whole process for Boost.MultiIndex is contained at the changeset: https://svn.boost.org/trac/boost/changeset/39922/ Alas the changeset includes other modifications not related to this, but I think it can give you an idea. Hope this helps a little. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo -- View this message in context: http://www.nabble.com/-interprocess--preparing-containers-tp20794468p2080277... Sent from the Boost - Dev mailing list archive at Nabble.com.

Joaquin M Lopez Munoz skrev:
The whole process for Boost.MultiIndex is contained at the changeset:
https://svn.boost.org/trac/boost/changeset/39922/
Alas the changeset includes other modifications not related to this, but I think it can give you an idea. Hope this helps a little.
Well, it helps a lot. Thanks. -Thorsten

Ion Gaztañaga skrev:
Thorsten Ottosen wrote: [snip]
In particular, if I want to use boost::ptr_vector, then do I need to have stateful allocators (both the normal container allocator, and the clone_allocator)?
Sorry, I'm not familiar with ptr_containers. If you can give me some hints on what's clone_allocator for, I'll be glad to help you to make ptr_container compatible with shared memory allocators. Just one issue: shared memory does not support virtual functions, so I don't think polymorphic cloning will be usable at all.
Currently the clone-allocators are a stateless customization point for cloning. It tells the containers how to clone the (indirectly) held pointees. I guess support for virtual functions is needed, except for the most trivial cases. So what does it mean exactly, that shared memory does not support virtual functions? Can I never call a virtual function on an object if that object's memory is shared? (In which case I'm a bit puzzled :-)) -Thorsten

----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com> To: <boost@lists.boost.org> Sent: Wednesday, December 03, 2008 10:17 AM Subject: Re: [boost] [interprocess] preparing containers
Ion Gaztañaga skrev:
Thorsten Ottosen wrote: [snip]
In particular, if I want to use boost::ptr_vector, then do I need to have stateful allocators (both the normal container allocator, and the clone_allocator)?
Sorry, I'm not familiar with ptr_containers. If you can give me some hints on what's clone_allocator for, I'll be glad to help you to make ptr_container compatible with shared memory allocators. Just one issue: shared memory does not support virtual functions, so I don't think polymorphic cloning will be usable at all.
Currently the clone-allocators are a stateless customization point for cloning. It tells the containers how to clone the (indirectly) held pointees.
I guess support for virtual functions is needed, except for the most trivial cases. So what does it mean exactly, that shared memory does not support virtual functions? Can I never call a virtual function on an object if that object's memory is shared? (In which case I'm a bit puzzled :-))
The address of the virtual table depends on the process, so can not be shared. As consequence we can not have virtual function on objects stored on shared memory. HTH, Vicente

vicente.botet skrev:
----- Original Message ----- From: "Thorsten Ottosen" <thorsten.ottosen@dezide.com>
I guess support for virtual functions is needed, except for the most trivial cases. So what does it mean exactly, that shared memory does not support virtual functions? Can I never call a virtual function on an object if that object's memory is shared? (In which case I'm a bit puzzled :-))
The address of the virtual table depends on the process, so can not be shared. As consequence we can not have virtual function on objects stored on shared memory.
Thanks. This pretty much makes it irrelevant for me to support shared memory then. best regards -Thorsten

Thorsten Ottosen wrote:
vicente.botet skrev:
The address of the virtual table depends on the process, so can not be shared. As consequence we can not have virtual function on objects stored on shared memory.
Thanks. This pretty much makes it irrelevant for me to support shared memory then.
best regards
-Thorsten
Thanks Vicente. For more limitations, see: http://tinyurl.com/6qxbws http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess/sharedmemorybetwe... Regards, Ion

Ion Gaztañaga skrev:
Thorsten Ottosen wrote:
vicente.botet skrev:
The address of the virtual table depends on the process, so can not be shared. As consequence we can not have virtual function on objects stored on shared memory.
Thanks. This pretty much makes it irrelevant for me to support shared memory then.
best regards
-Thorsten
Thanks Vicente. For more limitations, see:
Thanks. Does that mean I can't even use function pointers in shared memory? That is, I can't even create my own manual vtable scheme: class Base : boost::interprocess::base_class< Base* (), std::string (), void (const std::string&) > { Base* clone() const; std::string name() const; void setName( const std::string& ); }; ? Can I use boost::function in shared memory? -Thorsten

Thorsten Ottosen wrote:
Thanks. Does that mean I can't even use function pointers in shared memory? That is, I can't even create my own manual vtable scheme:
No, you can't. The address of a function is determined by the linker/loader so there is no valid address for several processes. The only way to do something similar would be to have all the possible functions in all processes, have a map/table for each process and an index that would be used to go to the table and call the address of the current process. Regards, Ion
participants (4)
-
Ion Gaztañaga
-
Joaquin M Lopez Munoz
-
Thorsten Ottosen
-
vicente.botet