The boost::intrusive_ptr (or a home-made version) at its simplest looks like this:
template<typename T>
class intrusive_ptr {
public:
intrusive_ptr(T* ptr) : ptr_(ptr)
{
if (ptr_) {
intrusive_ptr_add_ref(ptr_);
}
}
intrusive_ptr(const intrusive_ptr& that) : ptr_(that.ptr_)
{
if (ptr_) {
intrusive_ptr_add_ref(ptr_);
}
}
~intrusive_ptr()
{
if (ptr_) {
intrusive_ptr_release(ptr_);
}
}
// ...
private:
ptr_;
};
Usage:
class Foo {
public:
// ...
private:
std::size_t refcount_;
friend void intrusive_ptr_add_ref(const Foo* p)
{
++p->refcount_;
}
friend void intrusive_ptr_release(const Foo* p)
{
if (--p->refcount_ == 0) { // line 1
delete p; // line 2
}
}
};
intrusive_ptr<Foo> p(new Foo);
Apparently as Foo is implemented now, intrusive_ptr<Foo>s aren't thread-safe. Simply changing the type of Foo::refcount_ to std::atomic<std::size_t> won't suffice either, because when one thread is between line 1 and line 2, another thread may try to increase the reference count.
So my question is: Is it possible to make intrusive_ptr thread-safe, ideally without resorting to heavy mechanisms like mutexes?
Aucun commentaire:
Enregistrer un commentaire