|
Boost : |
From: Peter Dimov (pdimov_at_[hidden])
Date: 2005-04-03 07:03:29
Marcin Kaliciñski wrote:
> Hi Everybody,
>
> Smart pointers in boost work on a principle of preventing object
> destruction while references to it exist anywhere in the system. It
> causes that whoever owns a boost::shared_ptr to some object, has
> power to decide for how long will that object live. This is
> "ownership".
> In some situations it would be more convenient if object itself
> decided when to die (owned itself?), and notified all reference
> holders about this fact, so that they not try to use it any more.
You can do this with shared_ptr/weak_ptr.
> A real-life example from a computer game code. There are C++ objects
> representing tanks on the battlefield. When tank gets hit, it
> explodes and ceases to exist. The nice, straighforward way to do it
> is to write "delete this;" in C++. All references to deleted tank
> which are held by other tanks (for example those currently aiming at
> it, or following it), will be immediately updated to NULL, provided
> that they are live_ptrs: [...]
You can make the object own itself by adding a shared_ptr member to it that
holds a self-reference (this_). The self-destruction is accomplished with
this_.reset(). All weak_ptr instances will "expire". Or you can use a null
deleter if you want to delete the object explicitly and not use shared_ptr
to manage its lifetime:
http://boost.org/libs/smart_ptr/sp_techniques.html#weak_without_shared
but this solution has a drawback that I mention below.
In practice, my tanks are usually owned by a container (vector<
shared_ptr<Tank> > in the simplest case), because I need to enumerate them.
> template<class T>
> class live_ptr
> {
> // Member functions closely resembling those of shared_ptr
> // When object pointed to is deleted, this pointer resets its value
> to NULL
> };
The problem with providing such an interface is lack of reentrancy and
thread safety. Consider this code:
live_ptr<X> px;
if( px != 0 )
{
px->f();
}
If after the px != 0 check the object is deleted by a different thread,
px->f() will crash. This can also happen in some complex single threaded
code. weak_ptr::lock is designed to prevent this from happening by giving
you a shared_ptr to the object which keeps it alive.
> class Tank;
>
> void live_ptr_test()
> {
> Tank *tank = new Tank;
> live_ptr<Tank> p(tank); // not ownership, but a "live" reference
> delete tank;
> assert(p == 0);
> }
Your live_ptr<> requires support from Tank, right?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk