[shmem] Multiple allocator inheritence in containers

I noticed in the shmem implementation of the node based containers, multiple inheritence of allocators is used to provide the allocators of the three types required. This is going to add something like 8 extra bytes of overhead to the container for a allocator type of size 4, compared to having only a single allocator base class. Is there any reason not to create copies of a single allocator on demand? e.g. something like this: template<class T, class A, bool convertible_construct> struct shmem_list_alloc : public A { //... void priv_init() { //copy from A to make NodeAlloc m_node = NodeAlloc(static_cast<A&>(*this)).allocate(1); if(!boost::has_trivial_constructor<NodePtr>::value){ scoped_ptr<Node, Deallocator>node_deallocator(m_node, *this); //Make sure destructors are called before memory is freed //if an exception is thrown { typedef typename PtrAlloc::pointer NodePtrPtr; //copy allocator PtrAlloc ptrAlloc(static_cast<NodeAlloc&>(*this)); NodePtrPtr pnext(ptrAlloc.address(m_node->m_next)), pprev(ptrAlloc.address(m_node->m_prev)); ptrAlloc.construct(pnext, m_node); scoped_ptr<NodePtr, PtrDestructor> next_destroy(pnext, *this); ptrAlloc.construct(pprev, m_node); next_destroy.release(); } node_deallocator.release(); } else{ m_node->m_next = m_node; m_node->m_prev = m_node; } } That way you save 8 bytes in size, for presumably no measurable performance penalty from the cheap copying of the allocator. Obviously, any allocators used with this scheme must have the property that copies don't independently stop being == to each other, but that's almost required anyway for the multiple inheritence version. Tom

Hi Tom,
I noticed in the shmem implementation of the node based containers, multiple inheritence of allocators is used to provide the allocators of the three types required. This is going to add something like 8 extra bytes of overhead to the container for a allocator type of size 4, compared to having only a single allocator base class.
Is there any reason not to create copies of a single allocator on demand? e.g. something like this:
Some allocators are expensive to copy-construct. For example, boost::shmem::node_allocator<T> shares the same pool with other node_allocator<Y> instances of the same segment if sizeof(T)==sizeof(Y). The common pool must be searched in run time in the segment (you can't do the static pool trick like in multithreaded applications), and Shmem emulates this using "unique instance" mechanism, that basically constructs a map of objects created using this "unique instance" services indexed by name. So when creating that node allocators, the instance must search the common pool and create it if it is not already created (and do all this atomically holding a mutex). So constructing a node allocator is not cheap, and it can be quite expensive if there are many "unique instance" ("pseudo-singleton") variables. Dinkumware STL implementation also stores all allocators in the container. Shmem allocators have an optimization if the allocator::pointer has trivial constructor, and just stores two allocators instead of three. But if the allocator has an enhanced construct function: template<class Convertible> construct (const Convertible &convertible); instead of construct (const T &value); it can define an specialization of boost::shmem::has_convertible_construct<> so nodes can be constructed from the value_type directly. In this case, the container just stores one allocator. As you can suppose, all Shmem allocators have convertible construct. This optimization is described in the documentation. This problem is likely to change soon as rvalue reference standard proposal changes the construct function to a template: template<class T> construct (const T &&value); using T as a convertible type we can have less allocators stored without extensions. I don't like much that construct just allows one parameter. If the target type has a more complex constructor, we could take advantage in node constructors, because the container is who defines the node class. Regards, Ion
participants (2)
-
Ion Gaztañaga
-
Tom Widmer