用 C++11 编写的有界多生产者多消费者并发队列。
它经过实战考验并每天在生产中使用:
它被以下论文引用:
MPMCQueue< int > q ( 10 );
auto t1 = std::thread([&] {
int v;
q. pop (v);
std::cout << " t1 " << v << " n " ;
});
auto t2 = std::thread([&] {
int v;
q. pop (v);
std::cout << " t2 " << v << " n " ;
});
q.push( 1 );
q.push( 2 );
t1.join();
t2.join();
MPMCQueue<T>(size_t capacity);
构造一个新的MPMCQueue
保存类型为T
容量为capacity
项目。
void emplace(Args &&... args);
使用就地构造对项目进行排队。如果队列已满则阻塞。
bool try_emplace(Args &&... args);
尝试使用就地构造对项目进行排队。如果成功则返回true
,如果队列已满则返回false
。
void push(const T &v);
使用复制构造对项目进行排队。如果队列已满则阻塞。
template <typename P> void push(P &&v);
使用移动构造对项目进行排队。仅当std::is_nothrow_constructible<T, P&&>::value == true
时才参与重载决策。如果队列已满则阻塞。
bool try_push(const T &v);
尝试使用复制构造将项目排队。如果成功则返回true
,如果队列已满则返回false
。
template <typename P> bool try_push(P &&v);
尝试使用移动构造将项目排队。仅当std::is_nothrow_constructible<T, P&&>::value == true
时才参与重载决策。成功则返回true
,如果队列已满则返回false
。
void pop(T &v);
通过将项目复制或移动到v
来使项目出队。如果队列为空则阻塞。
bool try_pop(T &v);
尝试通过将项目复制或移动到v
来使项目出队。成功则返回true
,如果队列为空则返回false
。
ssize_t size();
返回队列中的元素数量。
当队列为空并且至少有一个读者在等待时,大小可以为负数。由于这是一个并发队列,因此在所有读取器和写入器线程都加入之前,大小只是尽力猜测。
bool empty();
如果队列为空则返回 true。
由于这是一个并发队列,因此在所有读取器和写入器线程都已加入之前,这只是尽力猜测。
除了构造和销毁之外的所有操作都是线程安全的。
入队:
出队:
参考:
测试并发算法很困难。我使用两种方法来测试实现:
boost::lockfree::queue
等进行比较static_assert
std::hardware_destructive_interference_size
[[nodiscard]]
属性该项目由 Erik Rigtorp <[email protected]> 创建。