Shinya Kitaoka 810553
#pragma once
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
Shinya Kitaoka 120a6e
namespace TThread {
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
Shinya Kitaoka 120a6e
// Forward declarations
Shinya Kitaoka 120a6e
class ExecutorId;  // Private
Toshihiro Shimizu 890ddd
class Runnable;
Toshihiro Shimizu 890ddd
2fc36c
}  // namespace TThread
2fc36c
#ifdef _WIN32
2fc36c
template class DVAPI TSmartPointerT<tthread::runnable>;</tthread::runnable>
Toshihiro Shimizu 890ddd
#endif
2fc36c
namespace TThread {
2fc36c
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
Shinya Kitaoka 120a6e
  very execution code. Worker threads created internally by the task manager
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
  mutex-protected environment in order to make sure that signal emission is
Shinya Kitaoka 120a6e
consistent
Shinya Kitaoka 120a6e
  with the task status - in other words, so that \a queued controller-emitted
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
  \warning Thus, setting up blocking connections or blocking direct slots is \b
Shinya Kitaoka 120a6e
not \b
Shinya Kitaoka 120a6e
  supported and will typically result in deadlocks; furthermore, the same also
Shinya Kitaoka 120a6e
applies to
Shinya Kitaoka 120a6e
  slot calls to the Executor API, which would have the aforementioned mutex to
Shinya Kitaoka 120a6e
be
Toshihiro Shimizu 890ddd
  locked again.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  \warning In case the above blocking strategies are mandatory, the user should
Shinya Kitaoka 120a6e
add
Shinya Kitaoka 120a6e
  custom signals to be emitted inside the mutex-free run() block, just before or
Shinya Kitaoka 120a6e
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;
Shinya Kitaoka 120a6e
  connect(myTask, SIGNAL(myStarted(TThread::RunnableP)), myTask,
Shinya Kitaoka 120a6e
SLOT(onStarted(TThread::RunnableP)),
Shinya Kitaoka 120a6e
    Qt::BlockingQueuedConnection)   //theRunCode() waits for onStarted() to
Shinya Kitaoka 120a6e
complete
Toshihiro Shimizu 890ddd
  ..
Toshihiro Shimizu 890ddd
  \endcode
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \sa Executor class.
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
class DVAPI Runnable : public QObject, public TSmartObject {
Shinya Kitaoka 120a6e
  Q_OBJECT
Shinya Kitaoka 120a6e
  DECLARE_CLASS_CODE
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ExecutorId *m_id;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int m_load;
Shinya Kitaoka 120a6e
  int m_schedulingPriority;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  friend class Executor;     // Needed to confront Executor's and Runnable's ids
Shinya Kitaoka 120a6e
  friend class ExecutorImp;  // The internal task manager needs full control
Shinya Kitaoka 120a6e
                             // over the task
Shinya Kitaoka 38fd86
  friend class Worker;       // Workers force tasks to emit state signals
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Runnable();
Shinya Kitaoka 120a6e
  virtual ~Runnable();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! The central code of the task that is executed by a worker thread.
Shinya Kitaoka 120a6e
  virtual void run() = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  virtual int taskLoad();
Shinya Kitaoka 120a6e
  virtual int schedulingPriority();
Shinya Kitaoka 120a6e
  virtual QThread::Priority runningPriority();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Q_SIGNALS:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void started(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  void finished(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  void exception(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  void canceled(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  void terminated(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public Q_SLOTS:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  virtual void onStarted(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  virtual void onFinished(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  virtual void onException(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  virtual void onCanceled(TThread::RunnableP sender);
Shinya Kitaoka 120a6e
  virtual void onTerminated(TThread::RunnableP sender);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  inline bool needsAccumulation();
Shinya Kitaoka 120a6e
  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
Shinya Kitaoka 120a6e
  a good idea to dedicate a separate thread for it, especially in GUI
Shinya Kitaoka 120a6e
applications;
Toshihiro Shimizu 890ddd
  however, doing so eventually raises the problem of managing such intensive
Shinya Kitaoka 120a6e
  tasks in a way that constantly ensures the correct use of the machine
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
  The TThread namespace API contains two main classes, \b Runnable and \b
Shinya Kitaoka 120a6e
Executor,
Toshihiro Shimizu 890ddd
  which provide a way for implementing consistent threading strategies.
Toshihiro Shimizu 890ddd
\n \n
Shinya Kitaoka 120a6e
  In order to use the Executor class it is first necessary to install the thread
Shinya Kitaoka 120a6e
manager
Toshihiro Shimizu 890ddd
  into application code by calling the static method init() appropriately.
Toshihiro Shimizu 890ddd
\n \n
Shinya Kitaoka 120a6e
  Executors are then used to submit - or eventually remove - tasks for execution
Shinya Kitaoka 120a6e
into a
Shinya Kitaoka 120a6e
  separate working thread, by means of the \b addTask(), \b removeTask() and \b
Shinya Kitaoka 120a6e
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
Shinya Kitaoka 120a6e
  added by that same Executor - which easily reflects the idea of an Executor
Shinya Kitaoka 120a6e
representing
Toshihiro Shimizu 890ddd
  a group of tasks.
Toshihiro Shimizu 890ddd
\n \n
Shinya Kitaoka 120a6e
  Basic control over the execution strategy for the group of tasks submitted by
Shinya Kitaoka 120a6e
an Executor
Shinya Kitaoka 120a6e
  can be acquired using the setMaxActiveTasks() and setMaxActiveLoad() methods,
Shinya Kitaoka 120a6e
both granting
Toshihiro Shimizu 890ddd
  the possibility to bound the execution of tasks to custom maximum conditions.
Shinya Kitaoka 120a6e
  For example, use setMaxActiveTasks(1) to force the execution of 1 task only at
Shinya Kitaoka 120a6e
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
*/
Shinya Kitaoka 120a6e
class DVAPI Executor {
Shinya Kitaoka 120a6e
  ExecutorId *m_id;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  friend class ExecutorImp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Executor();
Shinya Kitaoka 120a6e
  ~Executor();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  static void init();
Shinya Kitaoka 120a6e
  static void shutdown();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void addTask(RunnableP task);
Shinya Kitaoka 120a6e
  void removeTask(RunnableP task);
Shinya Kitaoka 120a6e
  void cancelAll();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setMaxActiveTasks(int count);
Shinya Kitaoka 120a6e
  void setMaxActiveLoad(int load);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int maxActiveTasks() const;
Shinya Kitaoka 120a6e
  int maxActiveLoad() const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void setDedicatedThreads(bool dedicated, bool persistent = true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // not implemented
Shinya Kitaoka 120a6e
  Executor &operator=(const Executor &);
Shinya Kitaoka 120a6e
  Executor(const Executor &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace TThread
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // TTHREAD_H