basic functions and classes to allow multi-threading More...
Enumerations | |
enum class | MR::Thread::nthreads_t { MR::Thread::nthreads_t::UNINITIALISED , MR::Thread::nthreads_t::EXPLICIT , MR::Thread::nthreads_t::IMPLICIT } |
Functions | |
size_t | MR::Thread::number_of_threads () |
nthreads_t | MR::Thread::type_nthreads () |
size_t | MR::Thread::threads_to_execute () |
template<class Functor > | |
__Multi< typename std::remove_reference< Functor >::type > | MR::Thread::multi (Functor &&functor, size_t nthreads=threads_to_execute()) |
used to request multiple threads of the corresponding functor More... | |
template<class Functor > | |
__run< Functor >::type | MR::Thread::run (Functor &&functor, const std::string &name="unnamed") |
Execute the functor's execute method in a separate thread. More... | |
basic functions and classes to allow multi-threading
These functions and classes mostly provide a thin wrapper around the C++11 threads API. While they can be used as-is to develop multi-threaded applications, in practice the Thread-safe image looping and Thread-safe queue APIs provide much more convenient and powerful ways of developing robust and efficient applications.
|
strong |
|
inline |
used to request multiple threads of the corresponding functor
This function is used in combination with Thread::run or Thread::run_queue to request that the functor object be run in parallel using number threads of execution (defaults to Thread::threads_to_execute()).
size_t MR::Thread::number_of_threads | ( | ) |
the number of cores available for multi-threading, as specified in the variable NumberOfThreads in the MRtrix configuration file, or set using the -nthreads command-line option
|
inline |
Execute the functor's execute method in a separate thread.
Launch a thread by running the execute method of the object functor, which should have the following prototype:
The thread is launched by the constructor, and the destructor will wait for the thread to finish. The lifetime of a thread launched via this method is therefore restricted to the scope of the returned object. For example:
It is also possible to launch an array of threads in parallel, by wrapping the functor into a call to Thread::multi(), as follows:
Proper handling of exceptions in a multi-threaded context is non-trivial, and in general you should take every precaution to prevent threads from throwing exceptions. This means you should perform all error checking within a single-threaded context, before starting processing-intensive threads, so as to minimise the chances of anything going wrong at that stage.
In this implementation, the wait() function can be used to wait until all threads have completed, at which point any exceptions thrown will be displayed, and a futher exception re-thrown to allow the main application to catch the error (this could be the same exception that was originally thrown if a single thread was run). This means the application will continue processing if any of the remaining threads remain active, and it may be a while before the application itself is allowed to handle the error appropriately. If this behaviour is not appropriate, and you expect exceptions to be thrown occasionally, you should take steps to handle these yourself (e.g. by setting / checking some flag within your threads, etc.).
size_t MR::Thread::threads_to_execute | ( | ) |
the number of threads to execute for a particular task if some higher-level process has already executed multiple threads, do not want the lower-level process querying this function to also generate a large number of threads; instead the lower-level function should run explicitly single-threaded.
nthreads_t MR::Thread::type_nthreads | ( | ) |