|
Boost : |
From: David B. Held (dheld_at_[hidden])
Date: 2003-02-01 12:56:31
I started a new thread because the old one was getting hard to
follow on my newsreader from the excessive nesting. I realized
there is yet another problem with my scheme (which should come
as no suprise by now). This time, the problem is the copy c'tor.
Here's a recap:
storage::storage(storage const& rhs)
: pointee_(rhs.pointee_)
{ }
storage::~storage()
{ checked_delete(pointee_); }
void storage::release()
{ pointee_ = default_value(); }
ref_counted::ref_counted(ref_counted const& rhs)
: count_(rhs.count_)
{ }
ref_counted::~ref_counted()
{ delete count_; }
bool ref_counted::release(P const& p)
{
if (!--*count_) return true;
count_ = 0; return false;
}
smart_ptr::smart_ptr(smart_ptr const& rhs)
: storage(rhs), ownership(rhs), checking(rhs), conversion(rhs)
{ checking::on_init(p); }
smart_ptr::~smart_ptr()
{
if (!ownership::release(get_impl(*this)))
{
storage::release();
}
}
The problem is that while ref_counted indeed cleans up its count in
the face of later exceptions, it may do so prematurely. For instance,
if checking(rhs) were to throw, ~smart_ptr() does not get a chance
to call ownership::release(), which prevents ownership from deleting
the count. Similarly, if, for some reason, ownership(rhs) were to
throw, storage might prematurely free the resource. The two most
viable solutions I can think of are:
A) add scope guards to make sure the right thing is done no matter
who throws
B) require that copying be no-throw
The problem with A) is that it imposes a performance penalty on
copying, which might be seen as undesirable. The problem with B)
is that deep_copy would probably like to throw. I guess there is
a third option:
C) require no-throw semantics only for certain policy configurations
Which is, of course, what I've already suggested for the P const& p
c'tors. Comments?
Dave
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk