|
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.
ExecutorSometimes, 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.
FetchContentIf 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:
find_package()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.