blob: cea4522d6d71d145bb67be8ea0ebe03613086af6 [file] [log] [blame] [view]
Ben Claytone9ba0a92019-09-05 12:35:50 +01001# Marl
2
3Marl is a hybrid thread / fiber task scheduler written in C++ 11.
4
5## About
6
7Marl is a C++ 11 library that provides a fluent interface for running tasks across a number of threads.
8
9Marl uses a combination of fibers and threads to allow efficient execution of tasks that can block, while keeping a fixed number of hardware threads.
10
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000011Marl supports Windows, macOS, Linux, Fuchsia and Android (arm, aarch64, mips64, ppc64 (ELFv2), x86 and x64).
Ben Claytone9ba0a92019-09-05 12:35:50 +010012
Ben Clayton7121ee62019-11-15 16:46:36 +000013Marl has no dependencies on other libraries (with an exception on googletest for building the optional unit tests).
Ben Claytonfccbd752019-09-09 20:55:09 +010014
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000015Example:
16
17```cpp
18#include "marl/defer.h"
19#include "marl/event.h"
20#include "marl/scheduler.h"
Ben Claytone90568e2020-02-13 17:34:05 +000021#include "marl/waitgroup.h"
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000022
23#include <cstdio>
24
25int main() {
26 // Create a marl scheduler using the 4 hardware threads.
27 // Bind this scheduler to the main thread so we can call marl::schedule()
28 marl::Scheduler scheduler;
29 scheduler.bind();
30 scheduler.setWorkerThreadCount(4);
31 defer(scheduler.unbind()); // Automatically unbind before returning.
32
Ben Claytone90568e2020-02-13 17:34:05 +000033 constexpr int numTasks = 10;
34
35 // Create an event that is manually reset.
36 marl::Event sayHellow(marl::Event::Mode::Manual);
37
38 // Create a WaitGroup with an initial count of numTasks.
39 marl::WaitGroup saidHellow(numTasks);
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000040
41 // Schedule some tasks to run asynchronously.
Ben Claytone90568e2020-02-13 17:34:05 +000042 for (int i = 0; i < numTasks; i++) {
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000043 // Each task will run on one of the 4 worker threads.
44 marl::schedule([=] { // All marl primitives are capture-by-value.
Ben Claytone90568e2020-02-13 17:34:05 +000045 // Decrement the WaitGroup counter when the task has finished.
46 defer(saidHellow.done());
47
48 printf("Task %d waiting to say hello...\n", i);
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000049
50 // Blocking in a task?
51 // The scheduler will find something else for this thread to do.
52 sayHellow.wait();
53
54 printf("Hello from task %d!\n", i);
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000055 });
56 }
57
Ben Claytone90568e2020-02-13 17:34:05 +000058 sayHellow.signal(); // Unblock all the tasks.
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000059
Ben Claytone90568e2020-02-13 17:34:05 +000060 saidHellow.wait(); // Wait for all tasks to complete.
61
62 printf("All tasks said hello.\n");
63
64 // All tasks are guaranteed to complete before the scheduler is destructed.
Ben Claytonb2bfc0d2020-02-09 19:20:01 +000065}
66```
67
Ben Clayton569a9a42020-03-11 22:27:09 +000068
69## Benchmarks
70
71Graphs of several microbenchmarks can be found [here](https://google.github.io/marl/benchmarks).
72
73
Ben Claytonfccbd752019-09-09 20:55:09 +010074## Building
75
Ben Clayton7121ee62019-11-15 16:46:36 +000076Marl contains many unit tests and examples that can be built using CMake.
Ben Claytonfccbd752019-09-09 20:55:09 +010077
78Unit tests require fetching the `googletest` external project, which can be done by typing the following in your terminal:
79
80```bash
81cd <path-to-marl>
82git submodule update --init
83```
84
85### Linux and macOS
86
87To build the unit tests and examples, type the following in your terminal:
88
89```bash
90cd <path-to-marl>
91mkdir build
92cd build
93cmake .. -DMARL_BUILD_EXAMPLES=1 -DMARL_BUILD_TESTS=1
94make
95```
96
97The resulting binaries will be found in `<path-to-marl>/build`
98
99### Windows
100
Nicolas Capense901e9b2019-09-13 22:32:59 -0400101Marl can be built using [Visual Studio 2019's CMake integration](https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=vs-2019).
Ben Claytonfccbd752019-09-09 20:55:09 +0100102
103### Using Marl in your CMake project
104
105You can build and link Marl using `add_subdirectory()` in your project's `CMakeLists.txt` file:
106```cmake
107set(MARL_DIR <path-to-marl>) # example <path-to-marl>: "${CMAKE_CURRENT_SOURCE_DIR}/third_party/marl"
108add_subdirectory(${MARL_DIR})
109```
110
111This will define the `marl` library target, which you can pass to `target_link_libraries()`:
112
113```cmake
114target_link_libraries(<target> marl) # replace <target> with the name of your project's target
115```
116
Ben Claytonb2bfc0d2020-02-09 19:20:01 +0000117You may also wish to specify your own paths to the third party libraries used by `marl`.
118You can do this by setting any of the following variables before the call to `add_subdirectory()`:
Ben Claytonfccbd752019-09-09 20:55:09 +0100119
120```cmake
Ben Claytonb2bfc0d2020-02-09 19:20:01 +0000121set(MARL_THIRD_PARTY_DIR <third-party-root-directory>) # defaults to ${MARL_DIR}/third_party
122set(MARL_GOOGLETEST_DIR <path-to-googletest>) # defaults to ${MARL_THIRD_PARTY_DIR}/googletest
123add_subdirectory(${MARL_DIR})
Ben Claytonfccbd752019-09-09 20:55:09 +0100124```
Ben Clayton7121ee62019-11-15 16:46:36 +0000125
126---
127
128Note: This is not an officially supported Google product