Boost logo

Boost :

From: Jens Maurer (jmaurer_at_[hidden])
Date: 2000-03-03 16:25:25

Gavin Collings wrote:
> The above highlights a need for boost::shared_ptr<> to co-exist with other smart
> pointer implementations. The current 'policy' for boost::shared_ptr<> seems to
> be that it will accept ownership from raw pointers or std::auto_ptr<>, but will
> never give it back again.

Yes, and this is good.

> Since boost::shared_ptr<> and its kin only implement
> a sub-set of conceivable desired ownership semantics, this seems overly
> restrictive.

We already have boost::scoped_ptr and of course std::auto_ptr which
implement different ownership semantics.

> 1) Insist on the current policy, shared_ptr is closed (or at least as closed as
> it can be). Use shared_ptr in cases where auto_ptr would normally be used.

> 2) Accept the need to open up ownership to other shared_ptr implementations.


After all, if some library function specifies that it wants an
auto_ptr<> (see example in a previous message), it says "I assume
ownership and will delete the storage after I'm done". Now it's
the duty of the caller to ensure that nobody else has references
to the pointed-to storage, because it may become invalid any time.
There is no general way how the caller can achieve this if the
caller only has a smart pointer variant with shared ownership,
so mutual agreement in the caller's environment is required (i.e.
clear documentation and social engineering).

However, the caller may check the use count of its shared_ptr<>
copy and decide that it's the only copy around, and *then*
it would be safe to call release(). I think it will be
very difficult to only have one copy of a shared_ptr<> in
non-trivial programs using these. Proxy classes transfering
ownership in and out of function calls may help, but then
the use of proxies has to proliferate up the function
call chain (if we assume pass-by-value of the shared_ptr<>).
Now we've got the information that ownership should be passed
sprinkled around the code, and we could have used auto_ptr<>
throughout from the beginning.

Thus, it is not reasonable to initialize an auto_ptr<> with
a shared_ptr<>.

But, there are shared pointer variants such as linked_ptr<>
which can inform all other instances that the underlying
object is no longer managed by this linked_ptr<> cooperative.
With these, it would be safe to call release(), because
no other linked_ptr<> will try to delete the data storage,
and accesses will try to dereference a NULL pointer, with the
usual implementation-defined *bang*.

Let's think about the features we expect from a smart pointer,
and choose an appropriate implementation:

 (1) single ownership, noncopyable => scoped_ptr<> (we already
have get() followed by reset() as a release() substitute for
scoped_ptr<>, do we want to make that explicit?)
 (2) single ownership => auto_ptr<>

>From now on, all variants fulfill the STL container element

 (3) STL container element requirements (only) => shared_ptr<>,
 (4) May construct several times from a raw pointer => shared_in_ptr<>
 (5) safe release() possible => linked_ptr<>
 (6) garbage collection => cyclic_ptr<>

Thus, I think there are simply different requirements with
different trade-offs which warrant more than just three interface
variants for smart pointer classes.

Note that this view is orthogonal to the implementation view.
In each interface category, we should provide an optimized
implementation and thus replace shared_ptr<> with fast_shared_ptr<>,
if it's really better. Additionally, someone (only) using the
shared_ptr<> requirements may choose shared_in_ptr<> because
there's a special purpose application where performance matters
but intrusiveness doesn't.

Note also that this discussion is not about usage of the storage
pointed to, but only about storage management and ownership.
Functions should never specify some smart pointer as a parameter
type if they just want to access the object pointed to (that's
why there's a (const) reference, after all).

Jens Maurer.

Boost list run by bdawes at, gregod at, cpdaniel at, john at