$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Bronek Kozicki (brok_at_[hidden])
Date: 2004-01-15 05:24:23
On Wed, 14 Jan 2004 16:46:25 -0800 (PST), Sean Kelly wrote:
> Currently, there's no way to force a shared_ptr to release something once
> it has been given ownership of it. I've run into instances where I use a
There is a way, and I will show you how I did it in my production code
(single-threaded at this moment, but I think you will have no trouble to
make it concurrency-safe).
class node : public boost::noncopyable // plus some more parent classes
{
private:
struct deleter
{
bool released;
deleter() : released(false) {}
void operator() (node* p)
{
if (!released)
delete p;
}
};
friend class std::auto_ptr<node>;
friend void boost::checked_delete<node>(node* x);
typedef std::vector<boost::shared_ptr<node> > children_collection;
children_collection children2_;
node* parent_;
// ...
public:
std::auto_ptr<node> remove()
{
// ...
boost::shared_ptr<node> me;
{
children_collection children2;
for (children_collection::const_iterator ci =
parent_->children2_.begin(); ci != parent_->children2_.end(); ++ci)
{
// simplified, real production code is different
if (ci->get() != this)
children2.push_back(*ci);
else
me = (*ci);
}
parent_->children2_.swap(children2);
}
std::auto_ptr<node> me2;
{
// you would lock critical section or mutex here, and such
// synchronization primitive could be stored inside deleter
assert(me.unique());
me2.reset(me.get());
boost::get_deleter<deleter>(me)->released = true;
me.reset();
}
return me2;
}
}
It's bit complicated and I'm not happy with it, but it works and seems
to be reliable
B.