Skip to content

An unbounded, wait-free, enqueue optimized, C++ implementation of mpsc & spsc queue

License

Notifications You must be signed in to change notification settings

JaimePolidura/Wait-Free-Queues

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wait-Free-Queues

C++ Wait-Free implementation of multiple-producer single-consumer & single-producer single-consumer

Setup CMAKE

mkdir libs 
cd libs
git clone https://github.com/JaimePolidura/Wait-Free-Queues
project(your-project-name)

add_subdirectory(libs/Wait-Free-Queues)
include_directories(libs/Wait-Free-Queues)

add_executable(your-project-name main.cpp)

target_link_libraries(your-project-name PRIVATE wait-free-queues)

Single-Producer Single-Consumer

#include "wait-free-queues/wait-free-queues.h"

jaime::spsc_queue<int> my_queue{};

my_queue.enqueue();

std::optional<int> optional1 = my_queue.dequeue(); //Will return 1
std::optional<int> optional2 = my_queue.dequeue(); //Will be empty

Single-Producer Multiple-Consumer

Unordered

  • jaime::unordered_mpsc_queue contains an array of jaime::spsc_queue. Every producer thread has assigned an index.
  • FIFO enqueue order is not guaranteed. When a consumer calls dequeue(), it will iterate through the array until it finds a spsc_queue that returns an element, otherwise it will return an empty optional.
#include "wait-free-queues/wait-free-queues.h"

//Number of producer threads that will access the queue. It is recommended that it is a power of 2
jaime::unordered_mpsc_queue<int> * queue = new jaime::unordered_mpsc_queue<int>(2);

std::thread producer1 = std::thread{[queue](){
    queue->enqueue(1);
}};

std::thread producer2 = std::thread{[queue](){
    std::this_thread::sleep_for(std::chrono::seconds(5));
    queue->enqueue(2);
}};

join(producer1, producer2);

//Consumer
//FIFO enqueue order not guaranteed. The order could be 2, 1 or 1, 2
queue->dequeue();
queue->dequeue();

Ordered

  • Similiar to Single-Producer Multiple-Consumer
  • FIFO enqueue order is guaranteed. The queue will have an internal counter that is atomically incremented when a producer enqueues an item. So as a result, every enqueued element will have a unique, monotonically counter.
  • When the consumer dequeues an element it will save it's counter. So, the next time it wants to dequeue another element, the element's counter needs to be the same as the consumer's counter + 1.
  • Dequeue() is O(n) where n is the number of producers threads.
#include "wait-free-queues/wait-free-queues.h"

jaime::lock_free::ordered_mpsc_queue<int> * queue = new jaime::lock_free::ordered_mpsc_queue<int>(2);

std::thread producer1 = std::thread{[queue](){
    queue->enqueue(1);
}};
std::thread producer2 = std::thread{[queue](){
    std::this_thread::sleep_for(std::chrono::seconds(5));
    queue->enqueue(2);
}};

join(producer1, producer2);

//Consumer
//FIFO enqueue order is guaranteed. The order will be 1, 2 
queue->dequeue();
queue->dequeue();

About

An unbounded, wait-free, enqueue optimized, C++ implementation of mpsc & spsc queue

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published