General Utility Library for C++14
2.12
|
A pool of worker threads with a task queue.
A thread pool is created with make_thread_pool(). It immediately starts the desired number of worker threads and keeps them running until the object gets destroyed. Work is given to the pool with the add_task() function in the form of a function object or function pointer. Tasks are stored in a queue and executed in the order they were added. This makes a ThreadPool with a single thread effectively a serial task queue.
Each task is associated with a TaskHandle. This handle is returned by add_task() and can be used to query the status of the task or to remove it from the queue via cancel(). Tasks that are already running cannot be canceled.
Tasks can also be scheduled to start after a specific time point or after a certain delay. Each task can also be given a name, which is mainly useful for debugging. See the example for an introduction.
All public member functions are thread-safe.
On Linux, threads in the pool explicitly block the signals SIGALRM, SIGINT, SIGPIPE, SIGTERM, SIGURG, SIGUSR1, and SIGUSR2. This is done to prevent the threads from terminating the whole process if one of these signals is received.
#include <ThreadPool.h>
Inherits std::enable_shared_from_this< ThreadPool >.
Classes | |
class | TaskHandle |
A handle for a task that has (or had) been enqueued on a ThreadPool. More... | |
Public Types | |
using | TaskId = std::uint64_t |
A unique identifier for a task. | |
using | TimePoint = std::chrono::time_point< std::chrono::system_clock > |
using | Duration = TimePoint::duration |
Public Member Functions | |
~ThreadPool () | |
Destruct the ThreadPool and join all threads. More... | |
template<typename Function > | |
TaskHandle< invoke_result_t< Function, ThreadPool & > > | add_task (Function fct, TimePoint start_time={}, std::string name={}) |
Enqueue a task. More... | |
template<typename Function , std::enable_if_t< is_invocable< Function >::value, bool > = true> | |
TaskHandle< invoke_result_t< Function > > | add_task (Function fct, TimePoint start_time={}, std::string name={}) |
template<typename Function , std::enable_if_t< is_invocable< Function, ThreadPool & >::value, bool > = true> | |
TaskHandle< invoke_result_t< Function, ThreadPool & > > | add_task (Function fct, Duration delay_before_start, std::string name={}) |
template<typename Function , std::enable_if_t< is_invocable< Function >::value, bool > = true> | |
TaskHandle< invoke_result_t< Function > > | add_task (Function fct, Duration delay_before_start, std::string name={}) |
template<typename Function , std::enable_if_t< is_invocable< Function, ThreadPool & >::value, bool > = true> | |
TaskHandle< invoke_result_t< Function, ThreadPool & > > | add_task (Function fct, std::string name) |
template<typename Function , std::enable_if_t< is_invocable< Function >::value, bool > = true> | |
TaskHandle< invoke_result_t< Function > > | add_task (Function fct, std::string name) |
GUL_EXPORT std::size_t | cancel_pending_tasks () |
Remove all pending tasks from the queue. More... | |
GUL_EXPORT std::size_t | capacity () const noexcept |
Return the maximum number of pending tasks that can be queued. | |
GUL_EXPORT std::size_t | count_pending () const |
Return the number of pending tasks. | |
GUL_EXPORT std::size_t | count_threads () const noexcept |
Return the number of threads in the pool. | |
GUL_EXPORT std::vector< std::string > | get_pending_task_names () const |
Return a vector with the names of the tasks that are waiting to be executed. | |
GUL_EXPORT std::vector< std::string > | get_running_task_names () const |
Return a vector with the names of the tasks that are currently running. | |
GUL_EXPORT bool | is_full () const noexcept |
Determine whether the queue for pending tasks is full (at capacity). | |
GUL_EXPORT bool | is_idle () const |
Return true if the pool has neither pending tasks nor tasks that are currently being executed. | |
GUL_EXPORT bool | is_shutdown_requested () const |
Determine whether the thread pool has been requested to shut down. | |
Static Public Member Functions | |
static GUL_EXPORT std::shared_ptr< ThreadPool > | make_shared (std::size_t num_threads, std::size_t capacity=default_capacity) |
Create a thread pool with the desired number of threads and the specified capacity for enqueuing tasks. More... | |
Static Public Attributes | |
constexpr static std::size_t | default_capacity { 200 } |
Default capacity for the task queue. | |
constexpr static std::size_t | max_capacity { 10'000'000 } |
Maximum possible capacity for the task queue. | |
constexpr static std::size_t | max_threads { 10'000 } |
Maximum possible number of threads. | |
gul14::ThreadPool::~ThreadPool | ( | ) |
Destruct the ThreadPool and join all threads.
This destructor blocks until all threads have terminated. Work that has not yet been started in one of the threads gets canceled, but work that has already been assigned to a thread continues to be executed until it completes.
|
inline |
Enqueue a task.
There are multiple overloads of this function for variations of the arguments:
fct | A function object or function pointer to be executed. This function can have an arbitrary return type and may either take no arguments (T fct() ) or a reference to the ThreadPool by which it gets executed (T fct(ThreadPool&) ). |
start_time | Earliest time point at which the task is to be started |
name | Optional name for the task (mainly for debugging) |
std::runtime_error | is thrown if the queue is full. |
std::size_t gul14::ThreadPool::cancel_pending_tasks | ( | ) |
Remove all pending tasks from the queue.
This call removes all tasks that have not yet been started from the queue. It has no impact on tasks that are currently being executed.
|
static |
Create a thread pool with the desired number of threads and the specified capacity for enqueuing tasks.
The thread pool is allocated in a shared pointer, which is necessary so that task handles can access the pool safely. A ThreadPool cannot be constructed directly.
Referenced by gul14::make_thread_pool().