Implementation of shared_ptr

J

James Kanze

[...]
What's wrong with your compiler?

It's conform with C++03, which says that this must have type T*
I would like to say that the most frequent use for reference
counts are thread-safe objects. Because as long as the object
is thread local or dedicated to exactly one thread at one
time, there is simply no need for reference counts.

It depends. But reference counted pointers have been oversold.
But if the object has (some) thread-safe methods, it makes
sense, that more than one thread holds an active reference to
the object.

Typically (and I know that there are exceptions), having
"thread-safe methodes" (whatever that actually medans) doesn't
buy you much. Thread safety is better handled at a higher
level.
 
J

James Kanze

On Jan 30, 5:08 pm, Marcel Müller <[email protected]>
wrote:
How do you manage memory without them?
I think the most common usage for shared_ptr
(or equivalent) is memory management - nothing
to do with threading.

That's pretty much my impression as well. And typically (which
means not always), if the object supports copy, it shouldn't be
allocated dynamically to begin with, and if it doesn't, most of
the time, it will have an explicit lifetime, so reference
counting isn't appropriate.
 
J

Juha Nieminen

James said:
In general, if you're allocating objects dynamically, it's
because they have identity, and aren't copiable. (There are
doubtlessly exceptions, but they aren't that common.) So just
ban copy and assignment.

I'm not so sure it's the duty of a base class to impose some design
pattern on the derived classes, especially given that copying
reference-counted objects is trivial to make safe (just put an empty
copy constructor and assignment operator in the reference counter class).

I wouldn't say that cloning dynamically allocated objects is such a
rare thing to do.
 
B

Bertrand

Kai-Uwe Bux said:
Kai-Uwe Bux said:
fungus said:
This is a question about the implementation of shared_ptr:

Does shared_ptr allocate a little control block to hold the reference
count?
[snip]
An alternative (ignoring the custom deleter) is something like this:

template < typename T >
class linked_ptr {
T * pointer;
mutable linked_ptr * next;
public:
...
};

Here the shared_ptr objects for a given pointee form a circular linked
singly list (maybe, a variant with a doubly linked list is easier).
[snip]

Thinking about the assignment operator now, a doubly linked list is
definitely easier.


Best

Kai-Uwe Bux
Correct me if I'm wrong, but that would be harder to make work in
multi-threaded environment without resorting to ``heavy'' locking.
(Perhaps, it is only possible with the doubly-linked case where the
cyclical aspect is avoided.)
AFAIK, Boost implementation uses a lock anyway. But one of my colleagues
implemented a lock-free variant (it might have been for Solaris only
though). I haven't seen what he did (yet), but I have a feeling that it
was achievable because of the control block.
 
K

Kai-Uwe Bux

Bertrand said:
Kai-Uwe Bux said:
Kai-Uwe Bux said:
fungus wrote:

This is a question about the implementation of shared_ptr:

Does shared_ptr allocate a little control block to hold the reference
count? [snip]
An alternative (ignoring the custom deleter) is something like this:

template < typename T >
class linked_ptr {
T * pointer;
mutable linked_ptr * next;
public:
...
};

Here the shared_ptr objects for a given pointee form a circular linked
singly list (maybe, a variant with a doubly linked list is easier).
[snip]

Thinking about the assignment operator now, a doubly linked list is
definitely easier.
[snip]
Correct me if I'm wrong, but that would be harder to make work in
multi-threaded environment without resorting to ``heavy'' locking.
(Perhaps, it is only possible with the doubly-linked case where the
cyclical aspect is avoided.)
AFAIK, Boost implementation uses a lock anyway.

Even with a lock, the control block variant is definitely more straight
forward in the multi-threaded case: you put the lock within the control
block and make sure that the block in only accessed by one thread at a
time.

With the linked structure, you would have to embed a lock within each
pointer and every change would presumably have to lock the pointer, its
successor, and its predecessor.
But one of my colleagues
implemented a lock-free variant (it might have been for Solaris only
though). I haven't seen what he did (yet), but I have a feeling that it
was achievable because of the control block.

No comment: I don't know lock-free algorithms.


Best

Kai-Uwe Bux
 
J

James Kanze

I'm not so sure it's the duty of a base class to impose some
design pattern on the derived classes, especially given that
copying reference-counted objects is trivial to make safe
(just put an empty copy constructor and assignment operator in
the reference counter class).

So what is the duty of a base class, if it isn't to define a
contract that all derived classes have to obey? That's the only
reason we require base classes to begin with.
I wouldn't say that cloning dynamically allocated objects is
such a rare thing to do.

No, but the cloning only occurs in very limited, well defined
circumstances. And again, typically, it doesn't concern the few
classes where reference counting is relevant.
 
J

Juha Nieminen

James said:
So what is the duty of a base class, if it isn't to define a
contract that all derived classes have to obey? That's the only
reason we require base classes to begin with.

A non-copyable contract is not in any way mandatory for reference
counting. Requiring it makes no sense. It's a design issue which is not
directly related to reference counting, and thus it's not the duty of
the reference counter base class to impose it.
No, but the cloning only occurs in very limited, well defined
circumstances. And again, typically, it doesn't concern the few
classes where reference counting is relevant.

It's not the concern of the reference counter base class whether the
objects must be cloneable or not.
 
J

James Kanze

A non-copyable contract is not in any way mandatory for
reference counting. Requiring it makes no sense. It's a design
issue which is not directly related to reference counting, and
thus it's not the duty of the reference counter base class to
impose it.

Certainly, but 99 times out of a 100, if you need reference
counting, it's because the class is not copiable. So it makes
sense to just not make the reference counted base copiable.
Logically, of course, the "base", that is, the count, isn't
copiable. It does have identity. If for some reason the
derived class supports copy, it must still respect this
identity.
 

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
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top