Boost logo

Boost :

From: Gary Powell (Gary.Powell_at_[hidden])
Date: 2000-12-21 13:37:14


> What is the release method supposed to do when the use-count > 1 ?
>
I may take back my support for adding release() if a whole host of
complications keep arising, but for now I would want the following to occur:

If the method is shared, then you can't decrement the count. Otherwise, when
other use of the shared_ptr goes out of scope it will delete the data. Thus
invalidating the object holding the non counted pointer.

template<typename T>
T *shared_ptr<T>::release()
{
    if (use_count() > 1)
        return px;

    T *rtn = px;
    px = 0;

    return rtn;
}

Of course now more code changes

template<typename T>
void shared_ptr<T>::dispose()
{
   // must check that px exists.
   if (--*pn == 0) { if (px) delete px; delete pn; }
}

We could also delete pn at the time of call to release() but then a whole
host of other things won't work, like operator=(); As it is, operator*(),
will have undefined behaviour ( likely crash) if called on an shared_ptr<>
for which release() has been called. (That's ok behaviour for me.)

This of course leaks the pointer to the count (pn) This could be fixed by
making the counter negative which would indicate that the base pointer isn't
to be deleted. (This is getting ugly..)

template<typename T>
T *shared_ptr<T>::release()
{
    if (*pn > 0)
    {
        *pn = -*pn; // reverse sign
    }
    decrement();

    return px;
}

Of course now even more code changes Plus new fns are needed.

template<typename T>
void decrement()
{
   if (*pn > 0)
     --*pn;
   else
     ++*pn;
}

template<typename T>
void increment()
{
    if (*pn > 0)
      ++*pn;
    else
      --*pn;
}

// replace all ++*pn and --*pn with calls to increment() and decrement()

template<typename T>
long shared_ptr<T>::use_count() const
{
    return abs(*pn);
}

template<typename T>
void shared_ptr<T>::dispose()
{
        if (*pn > 1)
   {
      if (--*pn == 0 ) { delete px; delete pn; }
   }
   else
   {
      if (++*pn == 0 ) { delete pn; }
   }
}

Or it could be fixed by adding yet another flag, and instead of having a
long as *pn, use a struct { bool released; long count; }

  -gary-


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