• Stars
    star
    1,160
  • Rank 40,222 (Top 0.8 %)
  • Language
    C++
  • License
    MIT License
  • Created over 8 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A bounded multi-producer multi-consumer concurrent queue written in C++11

MPMCQueue.h

C/C++ CI License

A bounded multi-producer multi-consumer concurrent queue written in C++11.

It's battle hardened and used daily in production:

It's been cited by the following papers:

  • Peizhao Ou and Brian Demsky. 2018. Towards understanding the costs of avoiding out-of-thin-air results. Proc. ACM Program. Lang. 2, OOPSLA, Article 136 (October 2018), 29 pages. DOI: https://doi.org/10.1145/3276506

Example

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();

Usage

  • MPMCQueue<T>(size_t capacity);

    Constructs a new MPMCQueue holding items of type T with capacity capacity.

  • void emplace(Args &&... args);

    Enqueue an item using inplace construction. Blocks if queue is full.

  • bool try_emplace(Args &&... args);

    Try to enqueue an item using inplace construction. Returns true on success and false if queue is full.

  • void push(const T &v);

    Enqueue an item using copy construction. Blocks if queue is full.

  • template <typename P> void push(P &&v);

    Enqueue an item using move construction. Participates in overload resolution only if std::is_nothrow_constructible<T, P&&>::value == true. Blocks if queue is full.

  • bool try_push(const T &v);

    Try to enqueue an item using copy construction. Returns true on success and false if queue is full.

  • template <typename P> bool try_push(P &&v);

    Try to enqueue an item using move construction. Participates in overload resolution only if std::is_nothrow_constructible<T, P&&>::value == true. Returns true on success and false if queue is full.

  • void pop(T &v);

    Dequeue an item by copying or moving the item into v. Blocks if queue is empty.

  • bool try_pop(T &v);

    Try to dequeue an item by copying or moving the item into v. Return true on sucess and false if the queue is empty.

  • ssize_t size();

    Returns the number of elements in the queue.

    The size can be negative when the queue is empty and there is at least one reader waiting. Since this is a concurrent queue the size is only a best effort guess until all reader and writer threads have been joined.

  • bool empty();

    Returns true if the queue is empty.

    Since this is a concurrent queue this is only a best effort guess until all reader and writer threads have been joined.

All operations except construction and destruction are thread safe.

Implementation

Memory layout

Enqeue:

  1. Acquire next write ticket from head.
  2. Wait for our turn (2 * (ticket / capacity)) to write slot (ticket % capacity).
  3. Set turn = turn + 1 to inform the readers we are done writing.

Dequeue:

  1. Acquire next read ticket from tail.
  2. Wait for our turn (2 * (ticket / capacity) + 1) to read slot (ticket % capacity).
  3. Set turn = turn + 1 to inform the writers we are done reading.

References:

Testing

Testing concurrency algorithms is hard. I'm using two approaches to test the implementation:

  • A single threaded test that the functionality works as intended, including that the element constructor and destructor is invoked correctly.
  • A multithreaded fuzz test that all elements are enqueued and dequeued correctly under heavy contention.

TODO

  • Add allocator supports so that the queue could be used with huge pages and shared memory
  • Add benchmarks and compare to boost::lockfree::queue and others
  • Use C++20 concepts instead of static_assert if available
  • Use std::hardware_destructive_interference_size if available
  • Add API for zero-copy deqeue and batch dequeue operations
  • Add [[nodiscard]] attributes

About

This project was created by Erik Rigtorp <[email protected]>.

More Repositories

1

awesome-modern-cpp

A collection of resources on modern C++
HTML
11,654
star
2

awesome-lockfree

A collection of resources on wait-free and lock-free programming
1,752
star
3

SPSCQueue

A bounded single-producer single-consumer wait-free and lock-free queue written in C++11
C++
871
star
4

ipc-bench

Latency benchmarks of Unix IPC mechanisms
C
547
star
5

spartan

A collection of High-Frequency trading components
C++
270
star
6

udpreplay

Replay UDP packets from a pcap file
C++
256
star
7

HashMap

An open addressing linear probing hash table, tuned for delete heavy workloads
C++
197
star
8

Seqlock

An implementation of Seqlock in C++11
C++
179
star
9

nanomq

Ultra low latency messaging kernel
C++
152
star
10

c2clat

A tool to measure CPU core to core latency
C++
118
star
11

hiccups

Measures the system induced jitter ("hiccups") a CPU bound thread experiences
C++
104
star
12

efvicap

erfvicap is a packet capture tool for network adapters from Solarflare
C++
59
star
13

statkit

Statistics toolkit for JavaScript
JavaScript
51
star
14

TokenBucket

Lock-free implementation of the token bucket algorithm in C++
C++
50
star
15

Function

Heap allocation free version of C++11 std::function
C++
50
star
16

isatomic

Test if AVX vector loads and stores are atomic
C++
21
star
17

CharConv

Fast integer to string and string to integer conversion functions
C++
18
star
18

BinarySemaphore

Binary semaphore using futexes.
C++
9
star
19

RingMap

Hybrid data structure that acts like a ring buffer and map
C++
7
star
20

dotemacs

My emacs config
Emacs Lisp
6
star
21

go-pikchr

Pikchr wrapped for Go using WebAssembly. No cgo required.
Go
4
star
22

unats

A simple single threaded NATS client for C++.
C++
4
star
23

nordpool

Data preprocessing / munging scripts for Nordpool power market data
HTML
3
star
24

openonload

git import of https://www.openonload.org/
Shell
3
star
25

sfpl

Simple functional programming language
Python
2
star
26

go-graphviz

Graphviz wrapped for Go using WebAssembly. No cgo required.
CMake
2
star
27

spark-dht11

Spark app to read a DHT11 sensor and publish humidity and temperature as Spark variables
C++
2
star
28

gmbackup

Simple tool to backup a Gmail account
Go
2
star
29

t-amp

Tripath Class-T audio amplifier
1
star
30

anything-git

Anything sources for Git
Emacs Lisp
1
star
31

chipamp

A hand crafted power amplifier of the Gainclone type
1
star
32

sysjitter2

1
star
33

gccsense

Fork of http://cx4a.org/repo/gccsense.git
Emacs Lisp
1
star