Quantum is a full-featured and powerful C++ framework build on top of the Boost coroutine library. The framework allows users to dispatch units of work (a.k.a. tasks) as coroutines and execute them concurrently using the 'reactor' pattern.
- Header-only library and interface-based design.
- Full integration with Boost asymmetric coroutine library.
- Highly parallelized coroutine framework for CPU-bound workloads.
- Support for long-running or blocking IO tasks.
- Allows explicit and implicit cooperative yielding between coroutines.
- Task continuations and coroutine chaining for serializing work execution.
- Synchronous and asynchronous dispatching using futures and promises similar to STL.
- Support for streaming futures which allows faster processing of large data sets.
- Support for future references.
- Cascading execution output during task continuations (a.k.a. past futures).
- Task prioritization.
- Internal error handling and exception forwarding.
- Ability to write lock-free code by synchronizing coroutines on dedicated queues.
- Coroutine-friendly mutexes and condition variables for locking critical code paths or synchronizing access to external objects.
- Fast pre-allocated memory pools for internal objects and coroutines.
- Parallel
forEach
operations which can easily be chained to solve map-reduce problems. - Stats and more...
Quantum is very simple and easy to use:
using namespace Bloomberg::quantum;
// Define a coroutine
int getDummyValue(CoroContext<int>::Ptr ctx)
{
int value;
... //do some work
ctx->yield(); //be nice and let other coroutines run (optional cooperation)
... //do more work and calculate 'value'
return ctx->set(value);
}
// Create a dispatcher
Dispatcher dispatcher;
// Dispatch a work item to do some work and return a value
int result = dispatcher.post(getDummyValue)->get();
Chaining tasks can also be straightforward. In this example we produce various types in a sequence.
using namespace Bloomberg::quantum;
// Create a dispatcher
Dispatcher dispatcher;
auto ctx = dispatcher.postFirst([](CoroContext<int>::Ptr ctx)->int {
return ctx->set(55); //Set the 1st value
})->then<double>([](CoroContext<double>::Ptr ctx)->int {
// Get the first value and add something to it
return ctx->set(ctx->getPrev<int>() + 22.33); //Set the 2nd value
})->then<std::string>([](CoroContext<std::string>::Ptr ctx)->int {
return ctx->set("Hello world!"); //Set the 3rd value
})->finally<std::list<int>>([](CoroContext<std::list<int>>::Ptr ctx)->int {
return ctx->set(std::list<int>{1,2,3}); //Set 4th value
})->end();
int i = ctx->getAt<int>(0); //This will throw 'FutureAlreadyRetrievedException'
//since future was already read in the 2nd coroutine
double d = ctx->getAt<double>(1); //returns 77.33
std::string s = ctx->getAt<std::string>(2); //returns "Hello world!";
std::list<int>& listRef = ctx->getRefAt<std::list<int>>(3); //get list reference
std::list<int>& listRef2 = ctx->getRef(); //get another list reference.
//The 'At' overload is optional for last chain future
std::list<int> listValue = ctx->get(); //get list value
Quantum is a header-only library and as such no targets need to be built. To install simply run:
> cmake -Bbuild <options> .
> make install
Various CMake options can be used to configure the output:
QUANTUM_BUILD_DOC
: Build Doxygen documentation. DefaultOFF
.QUANTUM_ENABLE_DOT
: Enable generation of DOT viewer files. DefaultOFF
.QUANTUM_VERBOSE_MAKEFILE
: Enable verbose cmake output. DefaultON
.QUANTUM_ENABLE_TESTS
: Builds thetests
target. DefaultOFF
.QUANTUM_BOOST_STATIC_LIBS
: Link with Boost static libraries. DefaultON
.QUANTUM_BOOST_USE_MULTITHREADED
: Use Boost multi-threaded libraries. DefaultON
.QUANTUM_INSTALL_ROOT
: Specify custom install path. Default is/usr/local/include
for Linux orc:/Program Files
for Windows.BOOST_ROOT
: Specify a different Boost install directory.GTEST_ROOT
: Specify a different GTest install directory.
Note: options must be preceded with -D
when passed as arguments to CMake.
Run the following from the top directory:
> cmake -Bbuild -DQUANTUM_ENABLE_TESTS=ON <options> .
> make quantum_test
> cd build
> ctest
To use the library simply include <quantum/quantum.h>
in your application. Also, the following libraries must be included in the link:
boost_context
pthread
Quantum library is fully is compatible with C++11
, C++14
and C++17
language features. See compiler options below for more details.
The following compiler options can be set when building your application:
__QUANTUM_PRINT_DEBUG
: Prints debug and error information tostdout
andstderr
respectively.__QUANTUM_USE_DEFAULT_ALLOCATOR
: Disable pool allocation for internal objects (other than coroutines stacks) and use default system allocators instead.__QUANTUM_USE_DEFAULT_CORO_ALLOCATOR
: Disable pool allocation for coroutine stacks and use default system allocator instead.__QUANTUM_ALLOCATE_POOL_FROM_HEAP
: Pre-allocates object pool from heap instead of the application stack (default). This affects internal object allocations other than coroutines. Coroutine pools are always heap-allocated due to their size.
Various application-wide settings can be configured via ThreadTraits
, AllocatorTraits
and StackTraits
.
Please see the wiki page for a detailed overview of this library, use-case scenarios and examples.
For class description visit the API reference page.