# A single-producer, single-consumer lock-free queue for C++
This mini-repository has my very own implementation of a lock-free queue (that I designed from scratch) for C++.
It only supports a two-thread use case (one consuming, and one producing). The threads can't switch roles, though
you could use this queue completely from a single thread if you wish (but that would sort of defeat the purpose!).
Note: If you need a general-purpose multi-producer, multi-consumer lock free queue, I have [one of those too][mpmc].
This repository also includes a [circular-buffer SPSC queue][circular] which supports blocking on enqueue as well as dequeue.
## Features
- [Blazing fast][benchmarks]
- Compatible with C++11 (supports moving objects instead of making copies)
- Fully generic (templated container of any type) -- just like `std::queue`, you never need to allocate memory for elements yourself
(which saves you the hassle of writing a lock-free memory manager to hold the elements you're queueing)
- Allocates memory up front, in contiguous blocks
- Provides a `try_enqueue` method which is guaranteed never to allocate memory (the queue starts with an initial capacity)
- Also provides an `enqueue` method which can dynamically grow the size of the queue as needed
- Also provides `try_emplace`/`emplace` convenience methods
- Has a blocking version with `wait_dequeue`
- Completely "wait-free" (no compare-and-swap loop). Enqueue and dequeue are always O(1) (not counting memory allocation)
- On x86, the memory barriers compile down to no-ops, meaning enqueue and dequeue are just a simple series of loads and stores (and branches)
## Use
Simply drop the readerwriterqueue.h (or readerwritercircularbuffer.h) and atomicops.h files into your source code and include them :-)
A modern compiler is required (MSVC2010+, GCC 4.7+, ICC 13+, or any C++11 compliant compiler should work).
Note: If you're using GCC, you really do need GCC 4.7 or above -- [4.6 has a bug][gcc46bug] that prevents the atomic fence primitives
from working correctly.
Example:
```cpp
using namespace moodycamel;
ReaderWriterQueue<int> q(100); // Reserve space for at least 100 elements up front
q.enqueue(17); // Will allocate memory if the queue is full
bool succeeded = q.try_enqueue(18); // Will only succeed if the queue has an empty slot (never allocates)
assert(succeeded);
int number;
succeeded = q.try_dequeue(number); // Returns false if the queue was empty
assert(succeeded && number == 17);
// You can also peek at the front item of the queue (consumer only)
int* front = q.peek();
assert(*front == 18);
succeeded = q.try_dequeue(number);
assert(succeeded && number == 18);
front = q.peek();
assert(front == nullptr); // Returns nullptr if the queue was empty
```
The blocking version has the exact same API, with the addition of `wait_dequeue` and
`wait_dequeue_timed` methods:
```cpp
BlockingReaderWriterQueue<int> q;
std::thread reader([&]() {
int item;
#if 1
for (int i = 0; i != 100; ++i) {
// Fully-blocking:
q.wait_dequeue(item);
}
#else
for (int i = 0; i != 100; ) {
// Blocking with timeout
if (q.wait_dequeue_timed(item, std::chrono::milliseconds(5)))
++i;
}
#endif
});
std::thread writer([&]() {
for (int i = 0; i != 100; ++i) {
q.enqueue(i);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
});
writer.join();
reader.join();
assert(q.size_approx() == 0);
```
Note that `wait_dequeue` will block indefinitely while the queue is empty; this
means care must be taken to only call `wait_dequeue` if you're sure another element
will come along eventually, or if the queue has a static lifetime. This is because
destroying the queue while a thread is waiting on it will invoke undefined behaviour.
The blocking circular buffer has a fixed number of slots, but is otherwise quite similar to
use:
```cpp
BlockingReaderWriterCircularBuffer<int> q(1024); // pass initial capacity
q.try_enqueue(1);
int number;
q.try_dequeue(number);
assert(number == 1);
q.wait_enqueue(123);
q.wait_dequeue(number);
assert(number == 123);
q.wait_dequeue_timed(number, std::chrono::milliseconds(10));
```
## CMake
### Using targets in your project
Using this project as a part of an existing CMake project is easy.
In your CMakeLists.txt:
```
include(FetchContent)
FetchContent_Declare(
readerwriterqueue
GIT_REPOSITORY https://github.com/cameron314/readerwriterqueue
GIT_TAG master
)
FetchContent_MakeAvailable(readerwriterqueue)
add_library(my_target main.cpp)
target_link_libraries(my_target PUBLIC readerwriterqueue)
```
In main.cpp:
```cpp
#include <readerwriterqueue.h>
int main()
{
moodycamel::ReaderWriterQueue<int> q(100);
}
```
### Installing into system directories
As an alternative to including the source files in your project directly,
you can use CMake to install the library in your system's include directory:
```
mkdir build
cd build
cmake ..
make install
```
Then, you can include it from your source code:
```
#include <readerwriterqueue/readerwriterqueue.h>
```
## Disclaimers
The queue should only be used on platforms where aligned integer and pointer access is atomic; fortunately, that
includes all modern processors (e.g. x86/x86-64, ARM, and PowerPC). *Not* for use with a DEC Alpha processor (which has very weak memory ordering) :-)
Note that it's only been tested on x86(-64); if someone has access to other processors I'd love to run some tests on
anything that's not x86-based.
## More info
See the [LICENSE.md][license] file for the license (simplified BSD).
My [blog post][blog] introduces the context that led to this code, and may be of interest if you're curious
about lock-free programming.
[blog]: http://moodycamel.com/blog/2013/a-fast-lock-free-queue-for-c++
[license]: LICENSE.md
[benchmarks]: http://moodycamel.com/blog/2013/a-fast-lock-free-queue-for-c++#benchmarks
[gcc46bug]: http://stackoverflow.com/questions/16429669/stdatomic-thread-fence-has-undefined-reference
[mpmc]: https://github.com/cameron314/concurrentqueue
[circular]: readerwritercircularbuffer.h
没有合适的资源?快使用搜索试试~ 我知道了~
单一生产者消费者队列,支持阻塞和不阻塞,支持固定大小和扩容
共48个文件
vcxproj:10个
filters:10个
h:8个
需积分: 5 0 下载量 128 浏览量
2024-05-23
16:18:07
上传
评论
收藏 70KB ZIP 举报
温馨提示
代码结构清晰,易于理解和扩展。它使用了常见的队列操作如Enqueue和Dequeue,并且支持检查队列是否为空的方法IsEmpty。开发者可以根据自己的需求方便地集成到现有系统中。
资源推荐
资源详情
资源评论
收起资源包目录
readerwriterqueue-master.zip (48个子文件)
readerwriterqueue-master
CMakeLists.txt 2KB
LICENSE.md 2KB
readerwriterqueue.h 32KB
tests
common
simplethread.h 5KB
simplethread.cpp 2KB
unittests
makefile 711B
msvc10
unittests.sln 1KB
unittests.vcxproj.filters 1KB
unittests.vcxproj 8KB
minitest.h 3KB
msvc12
unittests.sln 1KB
unittests.vcxproj.filters 1KB
unittests.vcxproj 8KB
unittests.cpp 21KB
stabtest
makefile 652B
stabtest.cpp 2KB
msvc10
stabtest.vcxproj.filters 1KB
stabtest.sln 1KB
stabtest.vcxproj 8KB
msvc12
stabtest.vcxproj.filters 1KB
stabtest.sln 1KB
stabtest.vcxproj 8KB
benchmarks
makefile 712B
systemtime.h 763B
systemtime.cpp 3KB
msvc10
winbench.vcxproj.filters 2KB
winbench.sln 2KB
winbench.vcxproj 8KB
winbench-intel.vcxproj.filters 2KB
winbench-intel.vcxproj 8KB
msvc12
winbench.vcxproj.filters 2KB
winbench.sln 2KB
winbench.vcxproj 8KB
winbench-intel.vcxproj.filters 2KB
winbench-intel.vcxproj 8KB
ext
1024cores
spscqueue.h 3KB
folly
ProducerConsumerQueue.h 5KB
bench.cpp 16KB
msvc14
winbench.vcxproj.filters 2KB
winbench.sln 2KB
winbench.vcxproj 8KB
winbench-intel.vcxproj.filters 2KB
winbench-intel.vcxproj 8KB
atomicops.h 22KB
.gitignore 504B
readerwriterqueueConfig.cmake.in 79B
readerwritercircularbuffer.h 11KB
README.md 6KB
共 48 条
- 1
资源评论
ACamel
- 粉丝: 5
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 堆排序(Heap Sort)是一种基于比较的排序算法
- ebatis 是一个简单方便上手的声明式 Elasticsearch ORM 框架
- 威纶通触摸屏编程软件Easy builder pro V6.09.02安装包(2024.06).txt
- ES查询客户端,elasticsearch可视化工具 elasticsearch查询客户端
- html css js网页制作实例 dldtdd实现列表功能
- 用python制作的tts语音小工具
- 三菱PLC编程参考手册
- 吃豆人代码源码全套.cpp
- 快速了解学习「编译原理」都需要掌握哪些基础知识.pdf
- Verilog示例代码,以SMIC 12nm工艺库为例给出Tessent TCL脚本示例
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功