Ben Clayton | e9ba0a9 | 2019-09-05 12:35:50 +0100 | [diff] [blame] | 1 | # Marl |
| 2 | |
| 3 | Marl is a hybrid thread / fiber task scheduler written in C++ 11. |
| 4 | |
| 5 | ## About |
| 6 | |
| 7 | Marl is a C++ 11 library that provides a fluent interface for running tasks across a number of threads. |
| 8 | |
| 9 | Marl 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 Clayton | b2bfc0d | 2020-02-09 19:20:01 +0000 | [diff] [blame] | 11 | Marl supports Windows, macOS, Linux, Fuchsia and Android (arm, aarch64, mips64, ppc64 (ELFv2), x86 and x64). |
Ben Clayton | e9ba0a9 | 2019-09-05 12:35:50 +0100 | [diff] [blame] | 12 | |
Ben Clayton | 7121ee6 | 2019-11-15 16:46:36 +0000 | [diff] [blame] | 13 | Marl has no dependencies on other libraries (with an exception on googletest for building the optional unit tests). |
Ben Clayton | fccbd75 | 2019-09-09 20:55:09 +0100 | [diff] [blame] | 14 | |
Ben Clayton | b2bfc0d | 2020-02-09 19:20:01 +0000 | [diff] [blame] | 15 | Example: |
| 16 | |
| 17 | ```cpp |
| 18 | #include "marl/defer.h" |
| 19 | #include "marl/event.h" |
| 20 | #include "marl/scheduler.h" |
| 21 | |
| 22 | #include <cstdio> |
| 23 | |
| 24 | int 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 Clayton | fccbd75 | 2019-09-09 20:55:09 +0100 | [diff] [blame] | 62 | ## Building |
| 63 | |
Ben Clayton | 7121ee6 | 2019-11-15 16:46:36 +0000 | [diff] [blame] | 64 | Marl contains many unit tests and examples that can be built using CMake. |
Ben Clayton | fccbd75 | 2019-09-09 20:55:09 +0100 | [diff] [blame] | 65 | |
| 66 | Unit tests require fetching the `googletest` external project, which can be done by typing the following in your terminal: |
| 67 | |
| 68 | ```bash |
| 69 | cd <path-to-marl> |
| 70 | git submodule update --init |
| 71 | ``` |
| 72 | |
| 73 | ### Linux and macOS |
| 74 | |
| 75 | To build the unit tests and examples, type the following in your terminal: |
| 76 | |
| 77 | ```bash |
| 78 | cd <path-to-marl> |
| 79 | mkdir build |
| 80 | cd build |
| 81 | cmake .. -DMARL_BUILD_EXAMPLES=1 -DMARL_BUILD_TESTS=1 |
| 82 | make |
| 83 | ``` |
| 84 | |
| 85 | The resulting binaries will be found in `<path-to-marl>/build` |
| 86 | |
| 87 | ### Windows |
| 88 | |
Nicolas Capens | e901e9b | 2019-09-13 22:32:59 -0400 | [diff] [blame] | 89 | Marl 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 Clayton | fccbd75 | 2019-09-09 20:55:09 +0100 | [diff] [blame] | 90 | |
| 91 | ### Using Marl in your CMake project |
| 92 | |
| 93 | You can build and link Marl using `add_subdirectory()` in your project's `CMakeLists.txt` file: |
| 94 | ```cmake |
| 95 | set(MARL_DIR <path-to-marl>) # example <path-to-marl>: "${CMAKE_CURRENT_SOURCE_DIR}/third_party/marl" |
| 96 | add_subdirectory(${MARL_DIR}) |
| 97 | ``` |
| 98 | |
| 99 | This will define the `marl` library target, which you can pass to `target_link_libraries()`: |
| 100 | |
| 101 | ```cmake |
| 102 | target_link_libraries(<target> marl) # replace <target> with the name of your project's target |
| 103 | ``` |
| 104 | |
Ben Clayton | b2bfc0d | 2020-02-09 19:20:01 +0000 | [diff] [blame] | 105 | You may also wish to specify your own paths to the third party libraries used by `marl`. |
| 106 | You can do this by setting any of the following variables before the call to `add_subdirectory()`: |
Ben Clayton | fccbd75 | 2019-09-09 20:55:09 +0100 | [diff] [blame] | 107 | |
| 108 | ```cmake |
Ben Clayton | b2bfc0d | 2020-02-09 19:20:01 +0000 | [diff] [blame] | 109 | set(MARL_THIRD_PARTY_DIR <third-party-root-directory>) # defaults to ${MARL_DIR}/third_party |
| 110 | set(MARL_GOOGLETEST_DIR <path-to-googletest>) # defaults to ${MARL_THIRD_PARTY_DIR}/googletest |
| 111 | add_subdirectory(${MARL_DIR}) |
Ben Clayton | fccbd75 | 2019-09-09 20:55:09 +0100 | [diff] [blame] | 112 | ``` |
Ben Clayton | 7121ee6 | 2019-11-15 16:46:36 +0000 | [diff] [blame] | 113 | |
| 114 | --- |
| 115 | |
| 116 | Note: This is not an officially supported Google product |