Boost provides an atomic reference sample with a calculated generic pointer
Here is the corresponding code snippet and explanation of the various orders used:
class X { public: typedef boost::intrusive_ptr<X> pointer; X() : refcount_(0) {} private: mutable boost::atomic<int> refcount_; friend void intrusive_ptr_add_ref(const X * x) { x->refcount_.fetch_add(1, boost::memory_order_relaxed); } friend void intrusive_ptr_release(const X * x) { if (x->refcount_.fetch_sub(1, boost::memory_order_release) == 1) { boost::atomic_thread_fence(boost::memory_order_acquire); delete x; } } };
Increasing the reference counter can always be done using memory_order_relaxed: new links to the object can be formed from an existing link and transferring the existing link from one thread to another should already provide any necessary synchronization.
It is important to provide any possible access to the object in one thread (through an existing link) in order to happen before the object is deleted in another thread. This is achieved by "releasing" after resetting the link (any access to the object through this link, obviously, should have happened earlier), and "acquire" before deleting the object.
It would be possible to use memory_order_acq_rel for fetch_sub but this leads to unnecessary โacquireโ operations when the control counter has not yet reached level zero and may impose a fine on performance.
I cannot understand why the memory_order_acquire barrier memory_order_acquire needed before the delete x operation. In particular, how safe is the compiler / processor to reorder delete x memory operations to fetch_sub and test for x == 1 without violating single-threaded semantics?
EDIT I think my question was not very clear. Here is the paraphrased version:
Will the control dependency between reading x ( x->refcount_.fetch_sub(1, boost::memory_order_release) == 1 ) and the delete x operation provide any order guarantee? Even if we consider a single-threaded program, is it possible for the compiler / processor to reorder the instructions corresponding to delete x to fetch_sub and compare ?. It would be very helpful if the answer was as low as possible, and include an example scenario in which the delete operation will be reordered (without affecting the semantics of a single thread), which illustrates the need to maintain order.
c ++ multithreading boost shared-memory atomic
Scott peterson
source share