Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TTHREAD_H
Toshihiro Shimizu 890ddd
#define TTHREAD_H
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsmartpointer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <qthread></qthread>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef DVAPI
Toshihiro Shimizu 890ddd
#undef DVVAR
Toshihiro Shimizu 890ddd
#ifdef TNZCORE_EXPORTS
Toshihiro Shimizu 890ddd
#define DVAPI DV_EXPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_EXPORT_VAR
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define DVAPI DV_IMPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_IMPORT_VAR
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace TThread
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Initializes all TThread namespace components.
Toshihiro Shimizu 890ddd
void DVAPI init();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Closes all TThread components as soon as possible in a safe manner.
Toshihiro Shimizu 890ddd
//! \sa Executor::shutdown() method
Toshihiro Shimizu 890ddd
void DVAPI shutdown();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Forward declarations
Toshihiro Shimizu 890ddd
class ExecutorId; //Private
Toshihiro Shimizu 890ddd
class Runnable;
Toshihiro Shimizu 890ddd
Campbell Barton 107701
#if !(defined(MACOSX) || defined(LINUX))
Toshihiro Shimizu 890ddd
template class TSmartPointerT<runnable>;</runnable>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
typedef TSmartPointerT<runnable> RunnableP;</runnable>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Runnable class is the abstract model for user-defined tasks which can be
Toshihiro Shimizu 890ddd
  scheduled for execution into separate application threads.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  A user must first implement the run() method to provide a task with the
Toshihiro Shimizu 890ddd
  very execution code. Worker threads created internally by the task manager will
Toshihiro Shimizu 890ddd
  take ownership of the task and make it run() at the most appropriate time,
Toshihiro Shimizu 890ddd
  depending on the task load, insertion time and its scheduling priority.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  The scheduling priority of a task can be set by reimplementing the
Toshihiro Shimizu 890ddd
  \b schedulingPriority() method. Tasks whose scheduling priority is higher are
Toshihiro Shimizu 890ddd
  always started before compared to the others added by the same executor.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  The hosting thread's running priority may also be set reimplementing the
Toshihiro Shimizu 890ddd
  runningPriority() method; see QThread class documentation in Qt manual.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  A task's load is an important property that should be reimplemented in all
Toshihiro Shimizu 890ddd
  resource-consuming tasks. It enables the user to declare the approximate
Toshihiro Shimizu 890ddd
  CPU load produced by a task, allowing the task manager to effectively
Toshihiro Shimizu 890ddd
  calculate the most appropriate moment to run it.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \warning \n All built-in signals about the Runnable class are emitted in a
Toshihiro Shimizu 890ddd
  mutex-protected environment in order to make sure that signal emission is consistent
Toshihiro Shimizu 890ddd
  with the task status - in other words, so that \a queued controller-emitted canceled()
Toshihiro Shimizu 890ddd
  and terminated() signals are not delivered \a before started() or \a after
Toshihiro Shimizu 890ddd
  finished() and exception() worker-emitted signals.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \warning Thus, setting up blocking connections or blocking direct slots is \b not \b
Toshihiro Shimizu 890ddd
  supported and will typically result in deadlocks; furthermore, the same also applies to
Toshihiro Shimizu 890ddd
  slot calls to the Executor API, which would have the aforementioned mutex to be
Toshihiro Shimizu 890ddd
  locked again.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \warning In case the above blocking strategies are mandatory, the user should add
Toshihiro Shimizu 890ddd
  custom signals to be emitted inside the mutex-free run() block, just before or after
Toshihiro Shimizu 890ddd
  the actual code to be executed, like this:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \code
Toshihiro Shimizu 890ddd
  void MyTask::run()
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    try
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      emit myStarted(this);
Toshihiro Shimizu 890ddd
      theRunCode();
Toshihiro Shimizu 890ddd
      emit myFinished(this);
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    catch(...)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      emit myException(this);
Toshihiro Shimizu 890ddd
      throw;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  \endcode
Toshihiro Shimizu 890ddd
  \code
Toshihiro Shimizu 890ddd
  ..
Toshihiro Shimizu 890ddd
  MyTask* myTask = new MyTask;
Toshihiro Shimizu 890ddd
  connect(myTask, SIGNAL(myStarted(TThread::RunnableP)), myTask, SLOT(onStarted(TThread::RunnableP)),
Toshihiro Shimizu 890ddd
    Qt::BlockingQueuedConnection)   //theRunCode() waits for onStarted() to complete
Toshihiro Shimizu 890ddd
  ..
Toshihiro Shimizu 890ddd
  \endcode
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \sa Executor class.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
class DVAPI Runnable : public QObject, public TSmartObject
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Q_OBJECT
Toshihiro Shimizu 890ddd
	DECLARE_CLASS_CODE
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ExecutorId *m_id;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_load;
Toshihiro Shimizu 890ddd
	int m_schedulingPriority;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	friend class Executor;	//Needed to confront Executor's and Runnable's ids
Toshihiro Shimizu 890ddd
	friend class ExecutorImp; //The internal task manager needs full control over the task
Toshihiro Shimizu 890ddd
	friend class Worker;	  //Workers force tasks to emit state signals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Runnable();
Toshihiro Shimizu 890ddd
	virtual ~Runnable();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//! The central code of the task that is executed by a worker thread.
Toshihiro Shimizu 890ddd
	virtual void run() = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual int taskLoad();
Toshihiro Shimizu 890ddd
	virtual int schedulingPriority();
Toshihiro Shimizu 890ddd
	virtual QThread::Priority runningPriority();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Q_SIGNALS :
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		void
Toshihiro Shimizu 890ddd
		started(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	void finished(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	void exception(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	void canceled(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	void terminated(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public Q_SLOTS:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	virtual void onStarted(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	virtual void onFinished(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	virtual void onException(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	virtual void onCanceled(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
	virtual void onTerminated(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	inline bool needsAccumulation();
Toshihiro Shimizu 890ddd
	inline bool customConditions();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Executor class provides an effective way for planning the execution of
Toshihiro Shimizu 890ddd
  user-defined tasks that require separate working threads.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  When an application needs to perform a resource-consuming task, it is often
Toshihiro Shimizu 890ddd
  a good idea to dedicate a separate thread for it, especially in GUI applications;
Toshihiro Shimizu 890ddd
  however, doing so eventually raises the problem of managing such intensive
Toshihiro Shimizu 890ddd
  tasks in a way that constantly ensures the correct use of the machine resources - 
Toshihiro Shimizu 890ddd
  so that in any given time the CPU usage is maximal, but not overloaded.
Toshihiro Shimizu 890ddd
  Additional requests by the user may arise, including preferenced ordering
Toshihiro Shimizu 890ddd
  among tasks, the necessity of salvaging some CPU resources or threads for
Toshihiro Shimizu 890ddd
  incoming tasks, and so on.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  The TThread namespace API contains two main classes, \b Runnable and \b Executor,
Toshihiro Shimizu 890ddd
  which provide a way for implementing consistent threading strategies.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  In order to use the Executor class it is first necessary to install the thread manager
Toshihiro Shimizu 890ddd
  into application code by calling the static method init() appropriately.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  Executors are then used to submit - or eventually remove - tasks for execution into a
Toshihiro Shimizu 890ddd
  separate working thread, by means of the \b addTask(), \b removeTask() and \b cancelAll() methods.
Toshihiro Shimizu 890ddd
  Each Executor's visibility is always limited to the tasks that it submits -
Toshihiro Shimizu 890ddd
  so calling removeTask() or cancelAll() only affects the tasks previously
Toshihiro Shimizu 890ddd
  added by that same Executor - which easily reflects the idea of an Executor representing
Toshihiro Shimizu 890ddd
  a group of tasks.
Toshihiro Shimizu 890ddd
\n \n
Toshihiro Shimizu 890ddd
  Basic control over the execution strategy for the group of tasks submitted by an Executor
Toshihiro Shimizu 890ddd
  can be acquired using the setMaxActiveTasks() and setMaxActiveLoad() methods, both granting
Toshihiro Shimizu 890ddd
  the possibility to bound the execution of tasks to custom maximum conditions.
Toshihiro Shimizu 890ddd
  For example, use setMaxActiveTasks(1) to force the execution of 1 task only at a time, 
Toshihiro Shimizu 890ddd
  or setMaxActiveLoad(100) to set a single CPU core available for the group.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \sa \b Runnable class documentation.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
class DVAPI Executor
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ExecutorId *m_id;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	friend class ExecutorImp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Executor();
Toshihiro Shimizu 890ddd
	~Executor();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	static void init();
Toshihiro Shimizu 890ddd
	static void shutdown();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void addTask(RunnableP task);
Toshihiro Shimizu 890ddd
	void removeTask(RunnableP task);
Toshihiro Shimizu 890ddd
	void cancelAll();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setMaxActiveTasks(int count);
Toshihiro Shimizu 890ddd
	void setMaxActiveLoad(int load);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int maxActiveTasks() const;
Toshihiro Shimizu 890ddd
	int maxActiveLoad() const;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setDedicatedThreads(bool dedicated, bool persistent = true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	// not implemented
Toshihiro Shimizu 890ddd
	Executor &operator=(const Executor &);
Toshihiro Shimizu 890ddd
	Executor(const Executor &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace TThread
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif //TTHREAD_H