I am writing intrusive shared pointer and I am using C++11 <atomic> facilities for reference counter. Here are the relevant fragments of my code:
//...
mutable std::atomic<unsigned> count;
//...
void
SharedObject::addReference() const
{
std::atomic_fetch_add_explicit (&count, 1u,
std::memory_order_consume);
}
void
SharedObject::removeReference() const
{
bool destroy;
destroy = std::atomic_fetch_sub_explicit (&count, 1u,
std::memory_order_consume) == 1;
if (destroy)
delete this;
}
I have started with memory_order_acquire and memory_order_release first but then I convinced myself that memory_order_consume should be good enough. After further deliberation it seems to me that even memory_order_relaxed should work.
Now, the question is whether I can use memory_order_consume for the operations or could I use weaker ordering (memory_order_relaxed) or should I use stricter ordering?
deletestatement, I'd say that "acquire" in theaddReferenceand "release" in theremoveReferenceare the right orderings. But youraddReferenceshould also make sure that the counter wasn't zero!addReference()after the object is first created before it is assigned to aSharedPtr<>. Acquire/release semantics seems that it should always work. But is it not possible to use weaker ordering constraint and why not?addReference()/removeReference()or with unprotected access to instance ofSharedPtrwhich I would consider undefined behaviour.SharedPtrs as members themselves need to be protected by mutexes etc. the same as other members of its enclosing class.