#include <ThreadPool.h>
Classes | |
| struct | QMax |
| struct | Statistics |
Public Types | |
| using | TaskType = function< void()> |
| using | TaskID = Common::UniqueID< ThreadPool > |
| Names a task AddTask added - for AbortTask, IsPresent, IsRunning and WaitForTask. No two the same in a process, so one from another ThreadPool names none of this one's; nor does TaskID{}. | |
Public Member Functions | |
| ThreadPool () | |
| ~ThreadPool () | |
| nonvirtual Options | GetOptions () const |
| nonvirtual unsigned int | GetPoolSize () const |
| nonvirtual void | SetPoolSize (unsigned int poolSize) |
| nonvirtual TaskID | AddTask (const TaskType &task, const optional< Characters::String > &name=nullopt) |
| nonvirtual TaskID | AddTask (const TaskType &task, QMax qmax, const optional< Characters::String > &name=nullopt) |
| ... waiting for (or throwing if no) room in the queue, per qmax | |
| nonvirtual void | AbortTask (TaskID task, Time::DurationSeconds timeout=Time::kInfinity) |
| nonvirtual void | AbortTasks (Time::DurationSeconds timeout=Time::kInfinity) |
| nonvirtual bool | IsPresent (TaskID task) const |
| nonvirtual bool | IsRunning (TaskID task) const |
| nonvirtual void | WaitForTask (TaskID task, Time::DurationSeconds timeout=Time::kInfinity) const |
| nonvirtual Containers::Collection< TaskInfo > | GetTasks () const |
| returns GetPendingTasks () + GetRunningTasks () - but also some extra information about each task | |
| nonvirtual Containers::Collection< TaskID > | GetPendingTasks () const |
| nonvirtual Containers::Collection< TaskID > | GetRunningTasks () const |
| nonvirtual size_t | GetTasksCount () const |
| return total number of tasks, either pending, or currently running. | |
| nonvirtual size_t | GetPendingTasksCount () const |
| return GetPendingTasks ().size (), except probably much more efficient | |
| nonvirtual void | WaitForTasksDone (const Traversal::Iterable< TaskID > &tasks, Time::DurationSeconds timeout=Time::kInfinity) const |
| nonvirtual void | WaitForTasksDoneUntil (const Traversal::Iterable< TaskID > &tasks, Time::TimePointSeconds timeoutAt) const |
| nonvirtual void | ResetStatistics () |
| nonvirtual Statistics | GetCurrentStatistics () const |
| nonvirtual Characters::String | ToString () const |
The ThreadPool class creates a small fixed number of Thread objects, and lets you use them as if there were many more. You submit a task (a std::function) - named by the TaskID AddTask returns - and it gets eventually executed.
If as Task in the thread pool raises an exception - this will be IGNORED (except for the special case of Thread::AbortException which is used internally to end the threadpool or remove some threads). Because of this, your submitted runnable should take care of its own error handling internally.
ThreadPool mainly useful for servicing lost-cost calls/threads, where the overhead of constructing the thread is significant compared to the cost of performing the action, and where the priority & stacksize can all be predetermined and 'shared'. Also - where you want to CONTROL the level of thread creation (possibly to avoid DOS attacks or just accidental overloading).
Definition at line 75 of file ThreadPool.h.
| using Stroika::Foundation::Execution::ThreadPool::TaskType = function<void ()> |
This means periodically calling CheckForInterruption () and that any waits respect thread cancelation (stop_token).
Tasks may exit via exception, but nothing will be done with that exception (beyond DbgTrace logging). So generally not a good idea, except for ThreadAbort handling.
Definition at line 159 of file ThreadPool.h.
Names a task AddTask added - for AbortTask, IsPresent, IsRunning and WaitForTask. No two the same in a process, so one from another ThreadPool names none of this one's; nor does TaskID{}.
Definition at line 168 of file ThreadPool.h.
| Stroika::Foundation::Execution::ThreadPool::ThreadPool | ( | ) |
Definition at line 13 of file ThreadPool.inl.
| ThreadPool::~ThreadPool | ( | ) |
Destroying a threadpool implicitly calls AbortAndWaitForDone () and eats any errors (cannot rethrow).
Definition at line 144 of file ThreadPool.cpp.
| auto Stroika::Foundation::Execution::ThreadPool::GetOptions | ( | ) | const |
These options have have been modified by various APIs, and reflect the current state of options, not necessarily those that the ThreadPool was created with.
Definition at line 17 of file ThreadPool.inl.
| unsigned int ThreadPool::GetPoolSize | ( | ) | const |
This returns the number of threads in the pool (not the number of tasks). Note 0 is a legal size.
Definition at line 150 of file ThreadPool.cpp.
| void ThreadPool::SetPoolSize | ( | unsigned int | poolSize | ) |
SetPoolSize () is advisory. It attempts to add or remove entries as requested. Note - 0 is a legal size.
But under some circumstances, it will fail. For example, if tasks are busy running on all threads, the number of threads in the pool cannot be decreased.
Definition at line 156 of file ThreadPool.cpp.
| auto Stroika::Foundation::Execution::ThreadPool::AddTask | ( | const TaskType & | task, |
| const optional< Characters::String > & | name = nullopt |
||
| ) |
Push the given task into the queue (possibly blocking til space in the Q or throwing if no space in Q, but does NOT block waiting for Q to till).
if qmax is provided, it takes precedence over any default value associated with the ThreadPool (constructor). If neither provided (as an argument or associated with the pool, this is treated as no max, and the addition just proceeds.
If qMax provided (even indirectly), assure task q length doesn't exceed argument by waiting up to the qMax duration, and either timing out, or successfully add the task.
Returns the TaskID naming the task added - for AbortTask, IsPresent, IsRunning and WaitForTask.
Definition at line 24 of file ThreadPool.inl.
| void ThreadPool::AbortTask | ( | TaskID | task, |
| Time::DurationSeconds | timeout = Time::kInfinity |
||
| ) |
It is NOT an error to call this with a task that is not in the Queue (since it would be a race to try to find out if it was already executed.
It can cancel a task if it has not yet been started, or EVEN if its already in progress (see Thread::Abort - it sends abort signal)
The function doesn't return until the task has been successfully cancelled, or it throws if timeout.
Definition at line 234 of file ThreadPool.cpp.
| void ThreadPool::AbortTasks | ( | Time::DurationSeconds | timeout = Time::kInfinity | ) |
See AbortTask () - it aborts all tasks - if any.
Definition at line 275 of file ThreadPool.cpp.
| bool ThreadPool::IsPresent | ( | TaskID | task | ) | const |
returns true if queued OR actively running.
Definition at line 299 of file ThreadPool.cpp.
| bool ThreadPool::IsRunning | ( | TaskID | task | ) | const |
returns true actively running
Definition at line 319 of file ThreadPool.cpp.
| void ThreadPool::WaitForTask | ( | TaskID | task, |
| Time::DurationSeconds | timeout = Time::kInfinity |
||
| ) | const |
throws if timeout. Returns when task has completed (or if not in task q)
Definition at line 330 of file ThreadPool.cpp.
| auto ThreadPool::GetPendingTasks | ( | ) | const |
return all tasks which are queued, but haven't yet been assigned to a thread.
Definition at line 388 of file ThreadPool.cpp.
| auto ThreadPool::GetRunningTasks | ( | ) | const |
return all tasks which are currently running (assigned to some thread in the thread pool).
Definition at line 362 of file ThreadPool.cpp.
| size_t ThreadPool::GetTasksCount | ( | ) | const |
return total number of tasks, either pending, or currently running.
This is GetRunningTasks().size () + GetPendingTasks ().size (), or alternatively GetTasks.size (), but more efficient.
Definition at line 374 of file ThreadPool.cpp.
| void Stroika::Foundation::Execution::ThreadPool::WaitForTasksDone | ( | const Traversal::Iterable< TaskID > & | tasks, |
| Time::DurationSeconds | timeout = Time::kInfinity |
||
| ) | const |
Wait for the given amount of time for all (either given argument or all tasks in this thread pool) to be done.
When called with a specific set of tasks, this procedure waits for exactly those tasks. When called with no task argument, it waits until GetTaskCount () == 0.
Definition at line 33 of file ThreadPool.inl.
| void ThreadPool::WaitForTasksDoneUntil | ( | const Traversal::Iterable< TaskID > & | tasks, |
| Time::TimePointSeconds | timeoutAt | ||
| ) | const |
Wait for the given amount of time for all (either given argument or all tasks in this thread pool) to be done.
When called with a specific set of tasks, this procedure waits for exactly those tasks. When called with no task argument, it waits until GetTaskCount () == 0.
Definition at line 404 of file ThreadPool.cpp.
| void ThreadPool::ResetStatistics | ( | ) |
Definition at line 432 of file ThreadPool.cpp.
| auto ThreadPool::GetCurrentStatistics | ( | ) | const |
Definition at line 439 of file ThreadPool.cpp.
| String ThreadPool::ToString | ( | ) | const |
a helpful debug dump of the ThreadPool status
Definition at line 491 of file ThreadPool.cpp.