|
Boost Users : |
From: ostware (ostware_at_[hidden])
Date: 2003-05-15 01:09:28
--- In Boost-Users_at_[hidden], "Peter Dimov" <pdimov_at_m...> wrote:
> ostware wrote:
> >
> > class T : public enable_shared_from_this {
> > public:
> > T() {}
> > ~T()
> > {
> > shared_ptr<T> ptr = shared_from_this();
> > // trouble: exception, can't get a shared_ptr
>
> What are you trying to achieve with this? ~T has already started;
the object
> is on its way to A Better Place. Even if you could get a shared_ptr
to it,
> you can't stop the object's destruction. The shared_ptr would point to a
> destroyed T once ~T finishes.
(First off, thanks for the reply. I am feeling my way in the dark here
and I could easily be missing something obvious. But perhaps it would
help 'boost' to clarify or fix this, as needed.
I keep having that 'what is going on!' feeling from boost that I got
from STL, when I first started digging into it. But I am also excited
by the possiblities of boost. Onward! So...)
~T needs to tell another object it holds a pointer to (say class U)
that it is 'going away' during its destructor. T and U are loosely
connected, from two different libraries, and each holds a weak_ptr to
the other. When U finds out that T is 'going away' it needs to void
out its weak_ptr<T>. I am converting code where the weak_ptrs were
simple U* or T*.
I think this code distills it down as much as possible. Obviously
there is more going on, but I think this sums it up...
class T : enable_shared_from_this<T>
{
~T()
{
shared_ptr<U> u = m_u.lock();
if (u) {
shared_ptr<T> ptr(shared_from_this()); // exception!
u->UnsetT(ptr);
}
}
void SetU(shared_ptr<U> u)
{
shared_ptr<T> ptr(shared_from_this());
t->SetT(ptr);
m_u = u;
}
private:
weak_ptr<U> m_u;
};
class U
{
public:
void SetT(shared_ptr<T> t)
{
m_t = t;
}
void UnsetT(shared_ptr<T> t)
{
if (t == m_t.lock())
m_t.reset();
}
private:
weak_ptr<T> m_t;
};
main()
{
shared_ptr<T> t(new T);
shared_ptr<U> u(new U);
t->SetU(u);
t.reset();
// u->m_t should have been voided out
}
Your null_deleter suggestion was good. I tried it and it worked. So
using the below works...
~T()
{
shared_ptr<T> ptr(this, null_deleter());
m_u->UnsetT(ptr);
}
It also worked to move the use_count_-- down past dispose() in
boost/detail/shared_count.hpp::release()...
shared_count::release()
{
{
mutex_type::scoped_lock lock(mtx_);
long new_use_count = use_count_ - 1;
if (new_use_count != 0)
{
--use_count_;
--weak_count_;
return;
}
}
dispose();
use_count_ = new_use_count;
weak_release();
}
The use of the mutex doesn't look kosher, but you get the idea (and I
am handling thread safety elsewhere anyway).
So it seems that either (1) this is a bug to fix, or (2) it should be
documented that shared_from_this doesn't work in destructors (or
constructors for that matter).
Cheers... mo
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net