shared_ptr implementation in the upcoming C++ standard

J

Juha Nieminen

I was wondering: How will the shared_ptr type required by the upcoming
C++ standard be typically implemented?

An "easy" implementation is to have shared_ptr have two pointers
inside it, one to point to the data, and another to point to the
reference number, which the class allocates as necessary. However,
technically this is way more inefficient than it could be. It needlessly
makes the size of the class two pointers big, and the separate
allocation of one single integer value (for the reference count) wastes
memory.
A much more efficient implementation would be if the reference count
was somehow attached to the allocated data itself. This way the
shared_ptr can consist of one single pointer and it doesn't need to
allocate the reference count separately. Of course this would require
for the memory allocator to always allocate the additional space
required for the reference count (which would be wasted everywhere where
memory is allocated dynamically but shared_ptr is not used).
Are there other ways of doing this efficiently?

I am curious to know what kind of implementation will be expected for
shared_ptr in future compilers, the simple but wasteful one, or a more
efficient one.

How is it implemented in the boost library?
I am actually interested in knowing a more efficient way of
implementing this than the "easy" way I described above. Any pointers
(no pun intended)?
 
K

Kai-Uwe Bux

Juha said:
I was wondering: How will the shared_ptr type required by the upcoming
C++ standard be typically implemented?

An "easy" implementation is to have shared_ptr have two pointers
inside it, one to point to the data, and another to point to the
reference number, which the class allocates as necessary. However,
technically this is way more inefficient than it could be. It needlessly
makes the size of the class two pointers big, and the separate
allocation of one single integer value (for the reference count) wastes
memory.
A much more efficient implementation would be if the reference count
was somehow attached to the allocated data itself. This way the
shared_ptr can consist of one single pointer and it doesn't need to
allocate the reference count separately. Of course this would require
for the memory allocator to always allocate the additional space
required for the reference count (which would be wasted everywhere where
memory is allocated dynamically but shared_ptr is not used).
Are there other ways of doing this efficiently?

Not that I know of.

Part of the problem is that you can truct a shared_ptr from a raw pointer.
That is, the shared_ptr does not control the allocation of the pointee.
Therefore, embedding the reference count somehow within the pointee would
very likely have to involve some serious compiler magic, i.e., support from
the compiler not available to the application programmer. For instance, the
compiler could check through data flow analysis whether a raw pointer is
used with shared_ptr and in this case cause the allocation function to
reserve room for a reference count and a pointer to the deleter behind the
scenes.

I am curious to know what kind of implementation will be expected for
shared_ptr in future compilers, the simple but wasteful one, or a more
efficient one.

I would expect generic implementations of the standard library (i.e. those
that aim to be usable with many compilers) to use two pointers.
How is it implemented in the boost library?

I don't know of the top of my head, but Boost has a mailing list, and the
source code is available.
I am actually interested in knowing a more efficient way of
implementing this than the "easy" way I described above. Any pointers
(no pun intended)?


Best

Kai-Uwe Bux
 
C

Chris Thomasson

Juha Nieminen said:
I was wondering: How will the shared_ptr type required by the upcoming
C++ standard be typically implemented?

An "easy" implementation is to have shared_ptr have two pointers
inside it, one to point to the data, and another to point to the
reference number, which the class allocates as necessary. However,
technically this is way more inefficient than it could be. It needlessly
makes the size of the class two pointers big, and the separate
allocation of one single integer value (for the reference count) wastes
memory.
[...]

Here is a technique for atomic reference counted pointers:

http://appcore.home.comcast.net/vzoom/refcount

That smart-pointer provides a strong/basic thread-saftey level:

http://groups.google.com/group/comp.programming.threads/browse_frm/thread/e5167941d32340c6

You can do this with a single pointer to a reference count object. If you
use 2 contiguous pointers to represent a refcount object then you are going
to have to use DWCAS in order to do any lock-free operations on them.
 
J

Joe Greer

I was wondering: How will the shared_ptr type required by the
upcoming
C++ standard be typically implemented?

An "easy" implementation is to have shared_ptr have two pointers
inside it, one to point to the data, and another to point to the
reference number, which the class allocates as necessary. However,
technically this is way more inefficient than it could be. It
needlessly makes the size of the class two pointers big, and the
separate allocation of one single integer value (for the reference
count) wastes memory.

Generally they use two pointers, one to the object and one to a separately allocated block
of control information. This allows objects to be referred to unmodified and allows there
to be weak_ptr()s. weak_ptr() generally has a pointer to the control block instead of the
object and can create a shared_ptr() from that block if the object is still alive.
A much more efficient implementation would be if the reference count
was somehow attached to the allocated data itself. This way the
shared_ptr can consist of one single pointer and it doesn't need to
allocate the reference count separately. Of course this would require
for the memory allocator to always allocate the additional space
required for the reference count (which would be wasted everywhere
where memory is allocated dynamically but shared_ptr is not used).

This typically requires what's called an intrusive smart pointer. The problem with that
is that it is pretty difficult to handle weak pointers properly. What tends to happen is
that when you delete the object, the control info goes with it. This sort of leaves weak
pointers in the lurch. What has to happen is that the space for the control information
has to be allocated with the object, but not as part of the object. You could then delete
the object by directly invoking the destructor, but not release the memory until the
control block is finally released. There is a proposal to add a factory like that for C++
0x. We will see what becomes of it. The only downside I see is that the whole block
allocated for the object would remain alive as long as there was a weak_ptr() referring to
it.



joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,078
Latest member
MakersCBDBlood

Latest Threads

Top