manticore
Main thread executor
|
This repository implements a C++ class that allows worker threads to pass functions for execution on the main thread. It is intended for non-thread-safe third-party code where locking is insufficient, e.g., due to garbage collection. For example, we can use manticore to allow workers to execute R code that might trigger GC. This is useful for parallelizing functions that need to occasionally - but safely - call the R APIs.
The manticore function is based around the Executor
class, which should be used like below:
The above code initializes the Executor
and launches worker threads that request main thread execution via run()
. Meanwhile, the main thread is listening for worker requests via listen()
. This blocks until all workers call finish_thread()
, at which point the main thread is allowed to proceed.
Check out the reference documentation for more details.
Sometimes, the Executor::run()
function needs to be called from deep inside another library, with no opportunity to pass the actual Executor
object through the library's interface. (Looking at you, tatami_r.) In such cases, we should create a global Executor
object that can be called from anywhere. For standard source files, we can use extern
linkage, while for header-only libraries, we can use static
getters:
This allows us to do:
some_function()
can now be called inside a parallel context:
Note that some_function()
can also be called outside of a parallel context, i.e. without running initialize()
, finish_thread()
or listen()
. In such cases, it will run directly on the main thread, allowing developers to re-use the same function in serial applications.
If you're using CMake, you just need to add something like this to your CMakeLists.txt
:
Then you can link to manticore to make the headers available during compilation:
You can install the library by cloning a suitable version of this repository and running the following commands:
Then you can use find_package()
as usual:
If you're not using CMake, the simple approach is to just copy the files - either directly or with Git submodules - and include their path during compilation with, e.g., GCC's -I
.