GemaCoreLib
The GeMA Core library
Public Member Functions | Static Public Member Functions | Private Types | Private Member Functions | Private Attributes | Static Private Attributes | Friends | List of all members
GmThreadManager Class Reference

Thread manager used for handling parallel executions. More...

#include <gmThreadManager.h>

Collaboration diagram for GmThreadManager:
Collaboration graph
[legend]

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...
 
LuaEnvthreadLuaEnv (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 GmLogCategorylogger ()
 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
 

Detailed Description

Thread manager used for handling parallel executions.

Constructor & Destructor Documentation

◆ GmThreadManager()

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.

Member Function Documentation

◆ addTask()

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.

◆ clearTaskQueues()

int GmThreadManager::clearTaskQueues ( )
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.

◆ currentId()

static int GmThreadManager::currentId ( )
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()

◆ maxWorkerThreads()

static int GmThreadManager::maxWorkerThreads ( )
inlinestatic

Returns the maximum number of allowed working threads.

Might be zero, forcing tasks to be executed by the main thread.

◆ numTasksInQueues()

int GmThreadManager::numTasksInQueues ( ) const
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.

◆ runTasks()

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.

◆ setCancelFlag()

void GmThreadManager::setCancelFlag ( bool  mode = true)
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

◆ setWorkerThreadLuaEnv()

void GmThreadManager::setWorkerThreadLuaEnv ( LuaEnv mainEnv,
const QList< LuaEnv * > &  envList 
)

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.

◆ taskAffinity()

const QVector<int>& GmThreadManager::taskAffinity ( ) const
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.


The documentation for this class was generated from the following files: