我需要以循环方式使用的线程安全的缓冲对象池。我通常只在其中放置一个互斥锁以使增量和模线程安全,但是可以使用std::atomic编写它吗?这是一个示例界面。如果使事情变得容易,缓冲区的总数可以是2的幂。在该类之外永远不会访问下一个缓冲区索引。

class Buffer;

class BufferManager
{
public:

    BufferManager( size_t totalBuffers = 8 ) : mNextBufferIndex( 0 ), mTotalBuffers( totalBuffers )
    {
        mBuffers = new Buffer*[mTotalBuffers];
    }

    Buffer* GetNextBuffer()
    {
        // How to make this operation atomic?
        size_t index = mNextBufferIndex;

        mNextBufferIndex = ( mNextBufferIndex + 1 ) % mTotalBuffers;

        return mBuffers[index];
    }

private:
    Buffer**            mBuffers;
    size_t              mNextBufferIndex;
    size_t              mTotalBuffers;
};

最佳答案

选择后可以安全使用Modulo

std::atomic<size_t> mNextBufferIndex;

    Buffer* GetNextBuffer()
    {
       // How to make this operation atomic?
       size_t index = mNextBufferIndex ++;

       size_t id = index % mTotalBuffers;

       // If size could wrap, then re-write the modulo value.
       // oldValue keeps getting re-read.
       // modulo occurs when nothing else updates it.
       size_t oldValue =mNextBufferIndex;
       size_t newValue = oldValue % mTotalBuffers;
       while (!m_mNextBufferIndex.compare_exchange_weak( oldValue, newValue, std::memory_order_relaxed ) )
            newValue = oldValue % mTotalBuffers;
       return mBuffers[id ];
    }

10-04 18:15