Skip to content

Commit f979fa8

Browse files
Merge pull request #5 from connectivecpp/develop
Merge develop to main
2 parents cd1a380 + 6ad5cca commit f979fa8

3 files changed

Lines changed: 28 additions & 8 deletions

File tree

‎README.md‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@
1010

1111
## Overview
1212

13-
`wait_queue` is a multi-reader, multi-writer FIFO queue (often called MPMC for multiple producer / multiple consumer) for transferring data between threads. It is templatized on the type of data passed through the queue as well as the queue container type. Data is passed with value semantics, either by copying or by moving (as opposed to a queue that transfers data by pointer or reference). The wait queue has both wait and no-wait pop semantics. A fixed size container (e.g. a `ring_span`) can be used, eliminating any and all dynamic memory management (useful in embedded or deterministic environments). Similarly, a circular buffer that only allocates on construction can be used, which eliminates dynamic memory management when pushing or popping values on or off the queue.
13+
`wait_queue` is a multi-reader, multi-writer FIFO wait queue (often called MPMC for multiple producer / multiple consumer) for transferring data between threads. It is templatized on the type of data passed through the queue as well as the queue container type. Data is passed with value semantics, either by copying or by moving (as opposed to a queue that transfers data by pointer or reference). The wait queue has both wait and no-wait pop semantics. A fixed size container (e.g. a `ring_span`) can be used, eliminating any and all dynamic memory management (useful in embedded or deterministic environments). Similarly, a circular buffer that only allocates on construction can be used, which eliminates dynamic memory management when pushing or popping values on or off the queue.
1414

15-
A graceful shutdown can be performed using the `request_stop` method (modeled on the C++ 20 `request_stop` from `std::stop_source`). This allows waiting reader threads to be notified for shutdown. Alternatively a `std::stop_token` can be passed in to the `wait_queue` constructor, allowing shutdown from outside of the `wait_queue` object.
16-
17-
`wait_queue` is inspired by code from Anthony Williams' Concurrency in Action book, although heavily modified.
18-
19-
Additional documentation can be found dkfjlkjdlkjklj
15+
Additional documentation (which is also the main page of the generated Doxygen doc) can be found [here](doc/README.md).
2016

2117
## Generated Documentation
2218

@@ -43,7 +39,7 @@ The unit test uses two third-party libraries (each is a single header-only file)
4339
- Martin Moene's [ring-span-lite](https://github.com/martinmoene/ring-span-lite)
4440
- Justas Masiulis' [circular_buffer](https://github.com/JustasMasiulis/circular_buffer)
4541

46-
Specific versions and / or branches for the dependencies are in `test/CMakeLists.txt`.
42+
Specific versions (or branches) for the dependencies are in `test/CMakeLists.txt`.
4743

4844
## Build and Run Unit Tests
4945

‎doc/Doxyfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ FILTER_SOURCE_PATTERNS =
10611061
# (index.html). This can be useful if you have a project on for instance GitHub
10621062
# and want to reuse the introduction page also for the doxygen output.
10631063

1064-
USE_MDFILE_AS_MAINPAGE = ../README.md
1064+
USE_MDFILE_AS_MAINPAGE = README.md
10651065

10661066
#---------------------------------------------------------------------------
10671067
# Configuration options related to source browsing

‎doc/README.md‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Wait Queue Detailed Overview
2+
3+
Multiple writer and reader threads can access a `wait_queue` simultaneously. When a value is pushed on the queue by a writer thread, only one reader thread will be notified to consume the value.
4+
5+
A graceful shutdown can be performed using the `request_stop` method (modeled on the C++ 20 `request_stop` from `std::stop_source`). This allows waiting reader threads to be notified for shutdown. Alternatively a `std::stop_token` can be passed in to the `wait_queue` constructor, allowing shutdown from outside of the `wait_queue` object.
6+
7+
Once `request_stop` has been invoked (either through `wait_queue` or from an external `std::stop_source`), subsequent pushes will not add any elements to the queue and the `push` methods will return `false`.
8+
9+
`wait_queue` uses C++ standard library concurrency facilities (e.g. `std::mutex`, `std::condition_variable_any`) in its implementation. It is not a lock-free queue, but it has been designed to be used in memory constrained environments or where deterministic performance is needed. In particular, `wait_queue`:
10+
11+
- Has been tested with Martin Moene's `ring_span` library for the internal container. A `ring_span` is traditionally known as a "ring buffer" or "circular buffer". This implies that the `wait_queue` can be used in environments where dynamic memory management (heap) is not allowed or is problematic. In particular, no heap memory is directly allocated within the `wait_queue` object.
12+
13+
- Does not throw or catch exceptions anywhere in its code base. Elements passed through the queue may throw exceptions, which must be handled at an application level. Exceptions may be thrown by C++ std library concurrency calls (`std::mutex` locks, etc), although this usually indicates an application design issue or issues at the operating system level.
14+
15+
- If the C++ std library concurrency calls become `noexcept` (instead of throwing an exception), every `wait_queue` method will become `noexcept` or conditionally `noexcept` (depending on the type of the data passed through the `wait_queue`).
16+
17+
The only requirement on the type passed through a `wait_queue` is that it supports either copy construction or move construction. In particular, a default constructor is not required (this is enabled by using `std::optional`, which does not require a default constructor).
18+
19+
The implementation is adapted from the book Concurrency in Action, Practical Multithreading, by Anthony Williams (2012 edition). The core logic in this library is the same as provided by Anthony in his book, but the API has changed and additional features added. The name of the utility class template in Anthony's book is `threadsafe_queue`.
20+
21+
The `push` methods return a `bool` to denote whether a value was succesfully queued or whether a shutdown was requested. The `pop` methods return a `std::optional` value. For `wait_and_pop`, if the value is not present it means a shutdown was requested. For `try_pop`, if the value is not present it means either the queue was empty at that moment, or that a shutdown was requested.
22+
23+
Each method is fully documented in the class documentation. In addition, a small amount of example code is present in the file level documentation.
24+

0 commit comments

Comments
 (0)