blob: da1f5a17bd5affa3d7f9692b361ea18262b1c25f [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"
21
22#include <cstdio>
23
24int main() {
25 // Create a marl scheduler using the 4 hardware threads.
26 // Bind this scheduler to the main thread so we can call marl::schedule()
27 marl::Scheduler scheduler;
28 scheduler.bind();
29 scheduler.setWorkerThreadCount(4);
30 defer(scheduler.unbind()); // Automatically unbind before returning.
31
32 // Create an event that automatically resets itself.
33 marl::Event sayHellow(marl::Event::Mode::Auto);
34 marl::Event saidHellow(marl::Event::Mode::Auto);
35
36 // Schedule some tasks to run asynchronously.
37 for (int i = 0; i < 10; i++) {
38 // Each task will run on one of the 4 worker threads.
39 marl::schedule([=] { // All marl primitives are capture-by-value.
40 printf("Task %d waiting to say hello!\n", i);
41
42 // Blocking in a task?
43 // The scheduler will find something else for this thread to do.
44 sayHellow.wait();
45
46 printf("Hello from task %d!\n", i);
47
48 saidHellow.signal();
49 });
50 }
51
52 // Unblock the tasks one by one.
53 for (int i = 0; i < 10; i++) {
54 sayHellow.signal();
55 saidHellow.wait();
56 }
57
58 // All tasks are guaranteed to completed before the scheduler is destructed.
59}
60```
61
Ben Claytonfccbd752019-09-09 20:55:09 +010062## Building
63
Ben Clayton7121ee62019-11-15 16:46:36 +000064Marl contains many unit tests and examples that can be built using CMake.
Ben Claytonfccbd752019-09-09 20:55:09 +010065
66Unit tests require fetching the `googletest` external project, which can be done by typing the following in your terminal:
67
68```bash
69cd <path-to-marl>
70git submodule update --init
71```
72
73### Linux and macOS
74
75To build the unit tests and examples, type the following in your terminal:
76
77```bash
78cd <path-to-marl>
79mkdir build
80cd build
81cmake .. -DMARL_BUILD_EXAMPLES=1 -DMARL_BUILD_TESTS=1
82make
83```
84
85The resulting binaries will be found in `<path-to-marl>/build`
86
87### Windows
88
Nicolas Capense901e9b2019-09-13 22:32:59 -040089Marl 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 +010090
91### Using Marl in your CMake project
92
93You can build and link Marl using `add_subdirectory()` in your project's `CMakeLists.txt` file:
94```cmake
95set(MARL_DIR <path-to-marl>) # example <path-to-marl>: "${CMAKE_CURRENT_SOURCE_DIR}/third_party/marl"
96add_subdirectory(${MARL_DIR})
97```
98
99This will define the `marl` library target, which you can pass to `target_link_libraries()`:
100
101```cmake
102target_link_libraries(<target> marl) # replace <target> with the name of your project's target
103```
104
Ben Claytonb2bfc0d2020-02-09 19:20:01 +0000105You may also wish to specify your own paths to the third party libraries used by `marl`.
106You can do this by setting any of the following variables before the call to `add_subdirectory()`:
Ben Claytonfccbd752019-09-09 20:55:09 +0100107
108```cmake
Ben Claytonb2bfc0d2020-02-09 19:20:01 +0000109set(MARL_THIRD_PARTY_DIR <third-party-root-directory>) # defaults to ${MARL_DIR}/third_party
110set(MARL_GOOGLETEST_DIR <path-to-googletest>) # defaults to ${MARL_THIRD_PARTY_DIR}/googletest
111add_subdirectory(${MARL_DIR})
Ben Claytonfccbd752019-09-09 20:55:09 +0100112```
Ben Clayton7121ee62019-11-15 16:46:36 +0000113
114---
115
116Note: This is not an officially supported Google product