【发布时间】:2021-04-12 10:14:36
【问题描述】:
我将http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue的C代码转换成C++。
在撰写本文时,如下所示:
struct MpscNode
{
std::atomic<MpscNode*> m_next;
};
class MpscQueue
{
private:
std::atomic<MpscNode*> m_head;
MpscNode* m_tail;
MpscNode m_stub;
public:
MpscQueue() : m_head(&m_stub), m_tail(&m_stub), m_stub{{nullptr}} { }
void push(MpscNode* node)
{
node->m_next.store(nullptr, std::memory_order_relaxed);
MpscNode* prev = m_head.exchange(node, std::memory_order_relaxed);
prev->m_next.store(node, std::memory_order_release);
}
MpscNode* pop()
{
MpscNode* tail = m_tail;
MpscNode* next = tail->m_next.load(std::memory_order_acquire);
if (tail == &m_stub)
{
if (nullptr == next)
return nullptr;
m_tail = next;
tail = next;
next = next->m_next.load(std::memory_order_acquire);
}
if (next)
{
m_tail = next;
return tail;
}
MpscNode* head = m_head.load(std::memory_order_relaxed);
if (tail != head)
return nullptr;
push(&m_stub);
next = tail->m_next.load(std::memory_order_acquire);
if (next)
{
// Remove node and return it.
m_tail = next;
return tail;
}
return nullptr;
}
};
您可以在这里查看最新版本,包括我的 cmets:https://github.com/CarloWood/ai-utils/blob/master/threading/MpscQueue.h
我的问题是关于push的第二行:
MpscNode* prev = m_head.exchange(node, std::memory_order_relaxed);
我不太确定这里使用的内存顺序。 看起来不错,但我想回顾一下我使用的内存顺序。
我无法测试它,因为我只有一个 Intel CPU - 而不是一个弱的 原子的(比如 -say- ARM)。
【问题讨论】:
-
我投票结束这个问题,因为它属于codereview.stackexchange.com。
-
@avh 我不敢苟同,因为这并不是审查代码的真正请求。问题是关于记忆顺序的正确使用以及记忆顺序的意义。一门高度专业的技术学科。此外,这是一种众所周知的(通用)算法,知道要使用的正确内存顺序是什么(原始设计缺少它们)将使很多人受益。
标签: c++ thread-safety memory-barriers memory-model stdatomic