This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Some questions on allocators and shared_ptr
- From: Jonathan Wakely <jwakely dot gcc at gmail dot com>
- To: Alex Dubov <oakad at yahoo dot com>
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Fri, 15 Oct 2010 09:39:05 +0100
- Subject: Re: Some questions on allocators and shared_ptr
- References: <loom.20101015T091214-474@post.gmane.org>
On 15 October 2010 08:50, Alex Dubov wrote:
> Greetings.
>
> I'm working on an updated version of rope<> class. Existing implementation has
> its own reference counting implementation, which is quite cumbersome. It tries
> to avoid touching reference count unless absolutely necessary, to gain some
> additional performance; additionally, it avoids using virtual inheritance to
> save some space in the tree nodes. I assume, that progress of the past 10 years
> made these tricks unnecessary, so shared_ptr<> can be used as is to simplify
> the structure of internal rope nodes.
>
> Same can probably be done to a basic_string<> and new __rc_string_base<> even,
> though, they have less need of it, dealing with only one node at a time.
>
> In respect to existing implementation of shared_ptr<> I encountered two issues:
>
> 1. In case custom allocator is used, _Sp_counted_deleter already stores a copy
> of it, however it is impossible to use it from "outside", thus additional copy
> of the allocator must be stored elsewhere (rope stores it in the held node
> objects to avoid passing it around as argument to every function). Much less
> useful deleter has a getter function nevertheless (I'm allocating my nodes with
> allocate_shared<>, relying on the built-in deleter object, as, I suppose, most
> people do in such cases).
>
> ?template<> _Alloc *get_alloc(shared_ptr<T>)
>
> 2. Leaf nodes (the ones containing actual character data) always require two
> allocations, as per variants:
> ?a. Allocate flexibly sized node object with place for character data, then
> invoke shared_ptr<> constructor with custom deleter resulting in second
> allocation.
> ?b. Allocate fixed size node object together with shared_ptr<> using
> allocate_shared<>, then allocate a string buffer separately.
>
> Needless to say, any "functional-like" string processing class will do a lot of
> leaf allocations, so there's a good reason to fold them into a single one.
>
> In many popular C APIs there's a convenient pattern, which may be expressed as:
>
> ?shared_ptr<T> allocate_shared(_Alloc __a, size_t extra, _Args... args);
>
> ?void *shared_ptr<T>::get_extra_ptr();
>
>
> Where "extra" is a size of additional raw byte buffer to allocate together with
> the user specified object. While not that pretty, such a function is easy to
> implement and it is very common in string manipulation classes (both string<>
> implementations in the library use it, and I suppose, containers do something
> similar as well).
>
>
> Is it possible/feasible to add the functionality described above as an
> extension to the library?
It would be possible, but it shouldn't be needed. Can you use the
aliasing feature of shared_ptr to make it unnecessary?
template<int N, typename Ch>
struct rope_storage {
std::array<N, Ch> data;
rope_node node;
};
auto raw
= allocate_shared<rope_storage<64, char>>(A,...);
shared_ptr<node> node(raw, raw->node);
Could you use something like this?