Boost logo

Boost :

From: Stewart, Robert (stewart_at_[hidden])
Date: 2002-01-17 09:28:32


From: Greg Colvin [SMTP:gcolvin_at_[hidden]]
>
> From: "Stewart, Robert" <stewart_at_[hidden]>
> > > From: Peter Dimov [SMTP:pdimov_at_[hidden]]
> > >
> > > As for release(), I think that it needs to be dropped.
> >
> > I recently created a special-purpose smart pointer that releases the ref
> > count of something relying on a C API. I wanted to write my functions
that
> > return such pointers to return smart pointer objects to ensure that the
ref
> > count was decreased even if I simply ignored the return value of such
> > functions. However, when returning to the calling C API, I needed to
turn
> > over the raw pointer in the return value, relinquishing ownership of it.
To
> > do that, I call release() on my smart pointer class (which, based upon
> > Andrei's insight, should be a non-member function).
> >
> > If I were using a Boost smart pointer without support for release(), how
> > would I relinquish ownership()? That is, how do I tell the Boost smart
> > pointer to not "deallocate" the pointer it holds, without release()?
>
> If I understand you, then I don't see why you need release().
> I imagine your code looks like this:
>
> extern "C" T* entry_point(T* p) {
>
> special_smart_ptr<T> wrapped_p(p);
>
> do_stuff_with(wrapped_p);
>
> assert(wrapped_p.unique());
>
> return p;
> }

Actually, it's like this:

extern "C"
T * f(stuff)
{
    special_smart_ptr<T> wrapped(foo(/* some arguments */));
    // do work with wrapped
    return wrapped.release();
}

where foo() looks like this:

special_smart_ptr<T>
foo(/* some parameters */)
{
    special_smart_ptr<T> result(/* create a T * in some way */);
    // do work with result, if appropriate
    return result;
}

foo() allocates a T *, according to the rules of the API I'm using, which
requires managing the reference count hidden behind that T *, which is
opaque. Therefore, since foo() allocates, it needs to ensure that the caller
knows to release that allocation, so it returns a special_smart_ptr<T> that
will decrement the reference count automatically unless the caller takes
ownership in some way.

Because f() calls foo(), it doesn't have access to the T * except through
"wrapped." However, when f() returns to the API, the API expects to manage
the reference count of the returned value, so "wrapped" shouldn't do it.
Therefore, f() calls special_smart_ptr::release() on "wrapped."

Does this make more sense now? How else would I do this, if not with
release()?

Rob
Susquehanna International Group, LLP
http://www.sig.com


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk