![]() |
GemaCoreLib
The GeMA Core library
|
Thread manager used for handling parallel executions. More...
#include <gmThreadManager.h>
Public Member Functions | |
GmThreadManager (GmSimulationData *simData) | |
Thread manager constructor. Reads the maximum number of threads from the simulation data "maxThreads" option value. More... | |
~GmThreadManager () | |
Destructor. Cancels any living threads and destroys every thread from the manager. | |
void | setWorkerThreadLuaEnv (LuaEnv *mainEnv, const QList< LuaEnv * > &envList) |
Sets the Lua environments associated with worker threads. More... | |
LuaEnv * | threadLuaEnv (int tid) const |
Returns the Lua environment associated with the given thread id. | |
void | addTask (GmThreadTask *task, int tid=0) |
Adds a task to the manager. The manager gets the task ownership and will delete it after execution. If tid is 0, the task can be executed by any thread. Otherwise it must be executed by the associated thread. This can be used to force the execution of a task by the same thread that executed a previous operation. More... | |
GmThreadTaskResult | runTasks (int nthreads) |
Executes the set of tasks in the queue using at most 'nthreads'. Waits for the threads to finish before returning. More... | |
void | execTasks (int nthreads) |
Similar to runTasks() but raising a lua error if the execution was either canceled or aborted. | |
const QVector< int > & | taskAffinity () const |
Returns a vector with size equal to the number of tasks executed in the last call to runTasks() storing, for each task, in the order in that they where added by addTask(), the id of the thread used to execute it. More... | |
int | numTasks () const |
Returns the number of tasks in the queue. | |
bool | cancelRequested () const |
Do we have a pending request to cancel the simulation? | |
bool | cancelPending () const |
Do we have a pending request to cancel the simulation or any other thread has aborted? | |
void | setCancelFlag (bool mode=true) |
Informs the thread manager that the user wants to cancel the simulation. Can be called from the server thread. More... | |
const GmLogCategory & | logger () |
Returns the thread manager logger. | |
Static Public Member Functions | |
static int | maxWorkerThreads () |
Returns the maximum number of allowed working threads. More... | |
static int | maxProcThreads () |
Returns the maximum number of concurrent threads supported by the processor. | |
static int | numProcCores () |
Returns the number of processor cores (physical processors - no hyper threading) | |
static int | currentId () |
Returns the id of the current thread, which MUST be either the main thread or a thread created by the thread manager. More... | |
static bool | inMainThread () |
Is the current thread the main thread? Equivalent to comparing the currentId() with 0. | |
Private Types | |
typedef QQueue< GmThreadTask * > | GmTaskQueue |
Type for a task queue. | |
Private Member Functions | |
int | clearTaskQueues () |
Removes any tasks from the queues, deleting them. Does NOT deletes the queues. It also does NOT resets _numTasks. Returns the number of deleted tasks. More... | |
int | numTasksInQueues () const |
Count the number of tasks in the task queues. More... | |
Private Attributes | |
GmThread * | _mainThread |
A pointer to a GmThread wrapper for the main thread. | |
QList< GmThread * > | _threadList |
A list with all the allocated threads. | |
GmTLS< GmTaskQueue, false > * | _taskQueues |
The task queues. Queue 0 is a global queue shared by all threads, while other queues can be used to match a task to a thread. Must be a pointer to avoid include order problems with GmTLS. | |
int | _numTasks |
The number of task added to the queues before runTasks() | |
int | _npendingTasks |
The number of still pending tasks. | |
QVector< int > | _taskAffinity |
The vector storing the id of the thread used to execute each task. | |
int | _maxAffinityId |
The biggest tid requested in a call to addTask() | |
int | _active |
Flag for controlling if runTasks is active, and how many threads should be used (prevents a thread to start running a task while still adding tasks to the queue + spurious wakes) | |
bool | _cancelRequested |
Flag for thread cancelation due to an external request / thread manager deletion. | |
bool | _abortRequested |
Flag for aborting tasks due to another task failure. | |
QMutex | _taskMutex |
The mutex controlling access to thread tasks. | |
QWaitCondition | _managerCond |
The condition variable used to block the manager until tasks are finished. | |
GmLogCategory | _logger |
Basic logger object for thread manager messages. | |
GmTLS< LuaEnv *, false > * | _luaEnv |
The per thread Lua environment. Must be a pointer to avoid include order problems with GmTLS. | |
Static Private Attributes | |
static int | _maxNumThreads = -1 |
The maximum number of threads that can be used. | |
static int | _maxProcThreads = 0 |
The maximum number of supported concurrent threads (logical processors) | |
static int | _numProcCores = 0 |
The number of processor cores (physical processors - no hyper threading) | |
Friends | |
class | GmThread |
Thread manager used for handling parallel executions.
GmThreadManager::GmThreadManager | ( | GmSimulationData * | simData | ) |
Thread manager constructor. Reads the maximum number of threads from the simulation data "maxThreads" option value.
If the maxThreads option is missing, or is equal to -1, the processor's maximum number of concurrent threads will be used. A value of zero disables threading, meaning that tasks will be executed by the main thread. A value of 1, although weird, can be used for testing: all tasks are executed by a single thread, different from the main one. Other negative values are interpreted as a multiple of the processor's maximum number of threads (-2 = twice the maximum).
IMPORTANT: This class is modeled so that there is only ONE thread manager. You can create a thread manager, delete it and then create another, but you can't have both at the same time. This is needed for the used GmTLS / GmTLBuffer schema to work.
IMPORTANT2: Never, ever, delete the thread manager if there still exists active GmTLS and GmTLBuffer objects. This will surelly lead to a crash when those objects are destroyed.
void GmThreadManager::addTask | ( | GmThreadTask * | task, |
int | tid = 0 |
||
) |
Adds a task to the manager. The manager gets the task ownership and will delete it after execution. If tid is 0, the task can be executed by any thread. Otherwise it must be executed by the associated thread. This can be used to force the execution of a task by the same thread that executed a previous operation.
IMPORTANT: If a thread id is given, that thread MUST participate on the task execution, meaning that the requested number of threads must be at least equal to that tid.
|
private |
Removes any tasks from the queues, deleting them. Does NOT deletes the queues. It also does NOT resets _numTasks. Returns the number of deleted tasks.
This function does not holds the mutex lock, so if that is needed, it should be acquired by the caller.
|
inlinestatic |
Returns the id of the current thread, which MUST be either the main thread or a thread created by the thread manager.
The main thread id is always 0, while other threads vary between 1 and maxWorkerThreads()
|
inlinestatic |
Returns the maximum number of allowed working threads.
Might be zero, forcing tasks to be executed by the main thread.
|
private |
Count the number of tasks in the task queues.
This function does not holds the mutex lock, so if that is needed, it should be acquired by the caller.
GmThreadTaskResult GmThreadManager::runTasks | ( | int | nthreads | ) |
Executes the set of tasks in the queue using at most 'nthreads'. Waits for the threads to finish before returning.
If the given number of threads is greater than the maximum number of threads or if equal to -1, the maximum will be considered. A value of 0 efectively disables thread usage meaning that tasks will be executed on the main thread. A value of 1, on the other hand, means that tasks will be executed by a single thread, other than the main one.
Returns GM_THREAD_OK if all the tasks completed ok. Returns GM_THREAD_ABORTED if any task was aborted by an error or GM_THREAD_CANCELED if the tasks where stoped by an external cancelation request.
|
inline |
Informs the thread manager that the user wants to cancel the simulation. Can be called from the server thread.
Even though this is technically a race condition (between setting the cancelation flag from the monitor server thread and other threads reading its value) we should be fine without any expensive synchronisation since setCancelFlag() and any matching cancelRequested() queries are only checking if a boolean value is different from zero. We are ok if the flag, as seen by other threads, gets changed from zero to anything different sometime in the future...
The mode parameter can be used to "reset" the thread manager to a running state after a cancellation. For test purposes only. Should not be used in a scenario where a a server cancelation request can be issued concurrently
Sets the Lua environments associated with worker threads.
The main thread Lua environment is needed when executin tasks in a 0 threads scenario. The environment list should have exactly maxWorkerThreads() entries.
Environments are NOT deleted by the thread manager.
IMPORTANT: This function should be called once before runing any tasks that need a Lua environment.
|
inline |
Returns a vector with size equal to the number of tasks executed in the last call to runTasks() storing, for each task, in the order in that they where added by addTask(), the id of the thread used to execute it.
The affinity information is filled by runTasks() and cleared upon the first call to addTask() after a call to runTasks(). If the vector will be used for defining target threads in calls to addTask(), it MUST be copied by the caller (since it will be cleared by the the first addTask()).
A value of -1 in the affinity vector means that the task was not executed.