【发布时间】:2012-03-16 01:40:14
【问题描述】:
短版:
我正在尝试替换来自 here 的无锁、单一生产者、单一消费者队列实现中使用的 C++11 中的 std::atomic。如何将其替换为 boost::atomic?
加长版:
我正在尝试通过工作线程从我们的应用中获得更好的性能。每个线程都有自己的任务队列。我们必须在每个任务出队/入队之前使用锁进行同步。
然后我找到了 Herb Sutter 关于无锁队列的文章。这似乎是一个理想的替代品。但是代码使用了来自 C++11 的std::atomic,我目前无法将其引入项目中。
更多的谷歌搜索导致了一些例子,例如this one for Linux (echelon's)和this one for Windows (TINESWARE's)。两者都使用平台的特定构造,例如 WinAPI 的 InterlockedExchangePointer 和 GCC 的 __sync_lock_test_and_set。
我只需要支持 Windows 和 Linux,所以也许我可以摆脱一些 #ifdefs。但我认为使用boost::atomic 提供的内容可能会更好。 Boost Atomic 还不是官方 Boost 库的一部分。所以我从http://www.chaoticmind.net/~hcb/projects/boost.atomic/ 下载了源代码,并在我的项目中使用了包含文件。
这是我目前得到的:
#pragma once
#include <boost/atomic.hpp>
template <typename T>
class LockFreeQueue
{
private:
struct Node
{
Node(T val) : value(val), next(NULL) { }
T value;
Node* next;
};
Node* first; // for producer only
boost::atomic<Node*> divider; // shared
boost::atomic<Node*> last; // shared
public:
LockFreeQueue()
{
first = new Node(T());
divider = first;
last= first;
}
~LockFreeQueue()
{
while(first != NULL) // release the list
{
Node* tmp = first;
first = tmp->next;
delete tmp;
}
}
void Produce(const T& t)
{
last.load()->next = new Node(t); // add the new item
last = last.load()->next;
while(first != divider) // trim unused nodes
{
Node* tmp = first;
first = first->next;
delete tmp;
}
}
bool Consume(T& result)
{
if(divider != last) // if queue is nonempty
{
result = divider.load()->next->value; // C: copy it back
divider = divider.load()->next;
return true; // and report success
}
return false; // else report empty
}
};
需要注意的一些修改:
boost::atomic<Node*> divider; // shared
boost::atomic<Node*> last; // shared
和
last.load()->next = new Node(t); // add the new item
last = last.load()->next;
和
result = divider.load()->next->value; // C: copy it back
divider = divider.load()->next;
我是否在这里正确地应用了来自 boost::atomic 的 load()(和隐式 store())?我们可以说这相当于 Sutter 最初的 C++11 无锁队列吗?
PS。我研究了 SO 上的许多线程,但似乎没有一个提供 boost::atomic 和无锁队列的示例。
【问题讨论】:
-
在您开始探索无锁马蜂窝之前,请考虑为您的工作线程提供更大的有效负载,以便花在互斥争用上的时间变得不那么重要。例如,如果您正在处理数据流,请将数据收集成大块,然后再将其传递给工作线程。
-
FWIF,请注意,Lockfree 库已被 Boost 接受:lists.boost.org/boost-announce/2011/08/0331.phptim.klingt.org/boost_lockfree
-
@EmileCormier 我会处理这个,谢谢。
-
@m3rLinEz 你的代码使用成功了吗?
-
正如 Igor R 提到的,无锁队列已经在 boost 中可用。可以直接使用。
标签: c++ multithreading boost atomic lock-free