C++11 atomics and intrusive shared pointer reference count

被刻印的时光 ゝ 提交于 2020-01-10 07:38:07

问题


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?


回答1:


void
SharedObject::addReference() const
{
    std::atomic_fetch_add_explicit (&count, 1u, std::memory_order_relaxed);
}

void
SharedObject::removeReference() const
{
    if ( std::atomic_fetch_sub_explicit (&count, 1u, std::memory_order_release) == 1 ) {
         std::atomic_thread_fence(boost::memory_order_acquire);
         delete this;
    }
}

You want to use atomic_thread_fence such that the delete is strictly after the fetch_sub. Reference

Quote from the linked text:

Increasing the reference counter can always be done with memory_order_relaxed: New references to an object can only be formed from an existing reference, and passing an existing reference from one thread to another must already provide any required synchronization.

It is important to enforce any possible access to the object in one thread (through an existing reference) to happen before deleting the object in a different thread. This is achieved by a "release" operation after dropping a reference (any access to the object through this reference must obviously happened before), and an "acquire" operation before deleting the object.

It would be possible to use memory_order_acq_rel for the fetch_sub operation, but this results in unneeded "acquire" operations when the reference counter does not yet reach zero and may impose a performance penalty.



来源:https://stackoverflow.com/questions/10268737/c11-atomics-and-intrusive-shared-pointer-reference-count

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!