|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef _DEBUG
|
|
Toshihiro Shimizu |
890ddd |
#define _STLP_DEBUG 1
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tthreadmessage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tsystem.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tatomicvar.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tthread.h"
|
|
Campbell Barton |
d0e335 |
#include "tthreadp.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <set></set>
|
|
Toshihiro Shimizu |
890ddd |
#include <deque></deque>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_pool.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <qmultimap></qmultimap>
|
|
Toshihiro Shimizu |
890ddd |
#include <qmutablemapiterator></qmutablemapiterator>
|
|
Toshihiro Shimizu |
890ddd |
#include <qmutex></qmutex>
|
|
Toshihiro Shimizu |
890ddd |
#include <qwaitcondition></qwaitcondition>
|
|
Toshihiro Shimizu |
890ddd |
#include <qmetatype></qmetatype>
|
|
Toshihiro Shimizu |
890ddd |
#include <qcoreapplication></qcoreapplication>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * The QMultiMap needs to be reverse-iterated to do that, since values with
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// refreshed, possibly adding new Workers for some executable tasks.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// the workers list. If no task can be taken, by default the thread exits and
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * A task is executable if, by default, its task load added to the sum of that of
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// (i.e.: 100 *
|
|
Toshihiro Shimizu |
890ddd |
// In other words, in every instant of execution, the sum of all active task's loads
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * When such default execution condition is not met when attempting to take the
|
|
Toshihiro Shimizu |
890ddd |
// task, no other task is taken instead - we wait until enough resources have been
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// for later execution and remove it from the global tasks queue - making it possible
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// "ACCUMULATION").
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// the global queue by Workers which ended a task, and this is done in a *BLOCKING* way
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// In other words, the order of execution is always that of global insertion, *inside
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * Most of the following code is mutex-protected, altough it might seem not - indeed,
|
|
Toshihiro Shimizu |
890ddd |
// only *one* mutex is locked and unlocked all of the time. This 'transition mutex' is
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * The transition mutex is *not* recursive. The reason is that threads con not wait on
|
|
Toshihiro Shimizu |
890ddd |
// QWaitConditions if the mutex is recursive. That makes it necessary (and welcome) to put
|
|
Toshihiro Shimizu |
890ddd |
// mutex lockers in strategic points of the code - in many low-level functions no mutex
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * Should the hosting thread wait for worker ones upon ExecutorImp destruction??
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// i puntatori in takeTask e refreshAss..
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace TThread;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DEFINE_CLASS_CODE(TThread::Runnable, 21)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Global init() initializer function
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TThread::init()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Executor::init();
|
|
Toshihiro Shimizu |
890ddd |
TThreadMessageDispatcher::init();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void TThread::shutdown()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Executor::shutdown();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace TThread
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Worker Thread class
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class Worker : public QThread
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
RunnableP m_task;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TSmartPointerT<executorid> m_master;</executorid>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool m_exit;
|
|
Toshihiro Shimizu |
890ddd |
QWaitCondition m_waitCondition;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Worker();
|
|
Toshihiro Shimizu |
890ddd |
~Worker();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void run();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void takeTask();
|
|
Toshihiro Shimizu |
890ddd |
inline bool canAdopt(const RunnableP &task);
|
|
Toshihiro Shimizu |
890ddd |
inline void adoptTask(RunnableP &task);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void rest();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void updateCountsOnTake();
|
|
Toshihiro Shimizu |
890ddd |
inline void updateCountsOnRelease();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void onFinish();
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// ExecutorId class
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! \sa Executor and Runnable class.
|
|
Toshihiro Shimizu |
890ddd |
class ExecutorId : public TSmartObject
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
size_t m_id;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_activeTasks;
|
|
Toshihiro Shimizu |
890ddd |
int m_maxActiveTasks;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_activeLoad;
|
|
Toshihiro Shimizu |
890ddd |
int m_maxActiveLoad;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool m_dedicatedThreads;
|
|
Toshihiro Shimizu |
890ddd |
bool m_persistentThreads;
|
|
Toshihiro Shimizu |
890ddd |
std::deque<worker *=""> m_sleepings;</worker>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorId();
|
|
Toshihiro Shimizu |
890ddd |
~ExecutorId();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void accumulate(const RunnableP &task);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void newWorker(RunnableP &task);
|
|
Toshihiro Shimizu |
890ddd |
void refreshDedicatedList();
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Executor::Imp class
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class ExecutorImp
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
QMultiMap<int, runnablep=""> m_tasks;</int,>
|
|
Toshihiro Shimizu |
890ddd |
std::set<worker *=""> m_workers;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::indices_pool<> m_executorIdPool;
|
|
Toshihiro Shimizu |
890ddd |
std::vector<uchar> m_waitingFlagsPool;</uchar>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int m_activeLoad;
|
|
Toshihiro Shimizu |
890ddd |
int m_maxLoad;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutex m_transitionMutex;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImp();
|
|
Toshihiro Shimizu |
890ddd |
~ExecutorImp();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void insertTask(int schedulingPriority, RunnableP &task);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void refreshAssignments();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline bool isExecutable(RunnableP &task);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImp *globalImp = 0;
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImpSlots *globalImpSlots = 0;
|
|
Toshihiro Shimizu |
890ddd |
bool shutdownVar = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImp::ExecutorImp()
|
|
Toshihiro Shimizu |
890ddd |
: m_activeLoad(0), m_maxLoad(TSystem::getProcessorCount() * 100), m_transitionMutex()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImp::~ExecutorImp()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//A task is executable <==> its load allows it. The task load is considered
|
|
Toshihiro Shimizu |
890ddd |
//fixed until another isExecutable() call is made again - in case it may
|
|
Toshihiro Shimizu |
890ddd |
//change in time.
|
|
Toshihiro Shimizu |
890ddd |
inline bool ExecutorImp::isExecutable(RunnableP &task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_activeLoad + task->m_load <= m_maxLoad;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void ExecutorImp::insertTask(int schedulingPriority, RunnableP &task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
task->m_schedulingPriority = schedulingPriority;
|
|
Toshihiro Shimizu |
890ddd |
m_tasks.insert(schedulingPriority, task);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Runnable::Runnable()
|
|
Toshihiro Shimizu |
890ddd |
: TSmartObject(m_classCode), m_id(0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Runnable::~Runnable()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_id)
|
|
Toshihiro Shimizu |
890ddd |
m_id->release(); //see Executor::addTask()
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Returns the predicted CPU load generated by the task, expressed in percentage
|
|
Toshihiro Shimizu |
890ddd |
//! of core usage (that is, 100 is intended to fully occupy one processing core).
|
|
Toshihiro Shimizu |
890ddd |
//! Appropriate task load calibration is an important step to take when implementing
|
|
Toshihiro Shimizu |
890ddd |
//! a new task; for this purpose, remember some rules to follow:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! task's load does not exceed the number of machine's processing cores multiplied
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! The task load is considered constant for the duration of the task. Changing its
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! The default task load is 0, representing a very light task. If the task load
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! a proportional number of threads simultaneously running to dispatch it; if this is
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int Runnable::taskLoad()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! with higher priority start before tasks with lower priority. The default
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! (std::numeric_limits<int>::max)() is acceptable.</int>
|
|
Toshihiro Shimizu |
890ddd |
int Runnable::schedulingPriority()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return 5;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QThread::Priority Runnable::runningPriority()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return QThread::NormalPriority;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline bool Runnable::customConditions()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (m_id->m_activeTasks < m_id->m_maxActiveTasks) &&
|
|
Toshihiro Shimizu |
890ddd |
(m_id->m_activeLoad + m_load <= m_id->m_maxActiveLoad);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\fn void Runnable::started(RunnableP sender)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
This signal is emitted from working threads just before the run() code
|
|
Toshihiro Shimizu |
890ddd |
is executed. Observe that the passed smart pointer ensures the survival of
|
|
Toshihiro Shimizu |
890ddd |
the emitting task for the time required by connected slots execution.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\warning The started(), finished() and exception() signals are emitted in
|
|
Toshihiro Shimizu |
890ddd |
a mutex-protected environment in order to provide the correct sequence of
|
|
Toshihiro Shimizu |
890ddd |
emissions (i.e. so that canceled() and terminated() controller-emitted signals
|
|
Toshihiro Shimizu |
890ddd |
are either delivered after started() and before finished() or exception(),
|
|
Toshihiro Shimizu |
890ddd |
or \a instead of them).
|
|
Toshihiro Shimizu |
890ddd |
\warning Thus, setting up blocking connections or \a direct slots that contain a
|
|
Toshihiro Shimizu |
890ddd |
blocking instruction or even calls to the Executor API (which would definitely
|
|
Toshihiro Shimizu |
890ddd |
try to relock the aforementioned mutex) is dangerous and could result in an
|
|
Toshihiro Shimizu |
890ddd |
application freeze.
|
|
Toshihiro Shimizu |
890ddd |
\warning In case it's necessary to use blocking features, they should be enforced
|
|
Toshihiro Shimizu |
890ddd |
through custom signals to be invoked manually in the run() method, outside the
|
|
Toshihiro Shimizu |
890ddd |
mutex.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\sa \b finished and \b exception signals.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\fn void Runnable::finished(RunnableP sender)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The \b finished signal is emitted from working threads once the run()
|
|
Toshihiro Shimizu |
890ddd |
code is returned without unmanaged exceptions.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\sa \b started and \b exception signals.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\fn void Runnable::exception(RunnableP sender)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The \b exception signal is emitted from working threads whenever an
|
|
Toshihiro Shimizu |
890ddd |
untrapped exception is found within the run() method.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\sa \b started and \b finished signals.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\fn void Runnable::canceled(RunnableP sender)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The \b canceled signal is emitted from the controller thread whenever
|
|
Toshihiro Shimizu |
890ddd |
a task which is currently under the task manager's control is canceled
|
|
Toshihiro Shimizu |
890ddd |
by the user (the signal is emitted from the thread invoking the cancel).
|
|
Toshihiro Shimizu |
890ddd |
Observe that tasks under execution are not stopped by the task manager
|
|
Toshihiro Shimizu |
890ddd |
when they are canceled, but the signal is emitted anyway - helping the
|
|
Toshihiro Shimizu |
890ddd |
user to stop the actual execution of the run() code in advance.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\sa \b Executor::removeTask and \b Executor::cancelAll methods.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
\fn void Runnable::terminated(RunnableP sender)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
The \b terminated signal is emitted from the controller thread when
|
|
Toshihiro Shimizu |
890ddd |
the Executor components are shutting down inside a call to
|
|
Toshihiro Shimizu |
890ddd |
Executor::shutdown(). Implementing a slot connected to this signal
|
|
Toshihiro Shimizu |
890ddd |
helps the user in controlling the flow of an Executor-multithreaded
|
|
Toshihiro Shimizu |
890ddd |
application when it is shutting down - for example, it can be imposed
|
|
Toshihiro Shimizu |
890ddd |
that the application must wait for the task to be finished, print logs
|
|
Toshihiro Shimizu |
890ddd |
or similar.
|
|
Toshihiro Shimizu |
890ddd |
This signal is always preceded by a canceled() signal, informing all
|
|
Toshihiro Shimizu |
890ddd |
active tasks that thay should begin quitting on their own in a 'soft'
|
|
Toshihiro Shimizu |
890ddd |
way before brute termination may occur.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\sa \b Executor::shutdown static method and \b Runnable::canceled signal.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Runnable::onStarted(RunnableP)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Runnable::onFinished(RunnableP)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Runnable::onException(RunnableP)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Runnable::onCanceled(RunnableP)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Runnable::onTerminated(RunnableP)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorId::ExecutorId()
|
|
Toshihiro Shimizu |
890ddd |
: m_activeTasks(0), m_maxActiveTasks(1), m_activeLoad(0), m_maxActiveLoad((std::numeric_limits<int>::max)()), m_dedicatedThreads(false), m_persistentThreads(false)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_id = globalImp->m_executorIdPool.acquire();
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_waitingFlagsPool.resize(globalImp->m_executorIdPool.size());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorId::~ExecutorId()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_dedicatedThreads) {
|
|
Toshihiro Shimizu |
890ddd |
m_persistentThreads = 0;
|
|
Toshihiro Shimizu |
890ddd |
refreshDedicatedList();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_executorIdPool.release(m_id);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExecutorId::refreshDedicatedList()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_dedicatedThreads || !m_persistentThreads) {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
unsigned int i, size = m_sleepings.size();
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < size; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
m_sleepings[i]->m_exit = true;
|
|
Toshihiro Shimizu |
890ddd |
m_sleepings[i]->m_waitCondition.wakeOne();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_sleepings.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Worker::Worker()
|
|
Toshihiro Shimizu |
890ddd |
: QThread(), m_task(0), m_master(0), m_exit(true)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Worker::~Worker()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Worker::run()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker sl(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (shutdownVar)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (;;) {
|
|
Toshihiro Shimizu |
890ddd |
//Run the taken task
|
|
Toshihiro Shimizu |
890ddd |
setPriority(m_task->runningPriority());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
try {
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT m_task->started(m_task);
|
|
Toshihiro Shimizu |
890ddd |
sl.unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_task->run();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sl.relock();
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT m_task->finished(m_task);
|
|
Toshihiro Shimizu |
890ddd |
} catch (...) {
|
|
Toshihiro Shimizu |
890ddd |
sl.relock(); //throw must be in the run() block
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT m_task->exception(m_task);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
updateCountsOnRelease();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (shutdownVar)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
takeTask();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_task) {
|
|
Toshihiro Shimizu |
890ddd |
onFinish();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_exit && !shutdownVar) {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_waitCondition.wait(sl.mutex());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//If this is the case, m_task == 0 and we return.
|
|
Toshihiro Shimizu |
890ddd |
if (!m_task || shutdownVar)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void Worker::updateCountsOnTake()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_activeLoad += m_task->m_load;
|
|
Toshihiro Shimizu |
890ddd |
m_task->m_id->m_activeLoad += m_task->m_load;
|
|
Toshihiro Shimizu |
890ddd |
++m_task->m_id->m_activeTasks;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void Worker::updateCountsOnRelease()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_activeLoad -= m_task->m_load;
|
|
Toshihiro Shimizu |
890ddd |
m_task->m_id->m_activeLoad -= m_task->m_load;
|
|
Toshihiro Shimizu |
890ddd |
--m_task->m_id->m_activeTasks;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void Worker::onFinish()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (m_master && m_master->m_dedicatedThreads && m_master->m_persistentThreads) {
|
|
Toshihiro Shimizu |
890ddd |
m_exit = false;
|
|
Toshihiro Shimizu |
890ddd |
m_master->m_sleepings.push_back(this);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_transitionMutex.unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_master = 0; //Master may be destroyed here - and m_exit= true for all sleepings
|
|
Toshihiro Shimizu |
890ddd |
//in that case
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_transitionMutex.lock();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
m_exit = true;
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_workers.erase(this);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Executor::Executor()
|
|
Toshihiro Shimizu |
890ddd |
: m_id(new ExecutorId)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_id->addRef();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Executor::~Executor()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_id->release();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! the application code. Be sure to use it according to the following rules:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Only QCoreApplications or QApplications may use Executors.
|
|
Toshihiro Shimizu |
890ddd |
//! This method must be invoked in a thread which performs constant Qt event
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Executor::init()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
//If no global ExecutorImp exists, allocate it now. You may not move this
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!globalImp) {
|
|
Toshihiro Shimizu |
890ddd |
globalImp = new ExecutorImp;
|
|
Toshihiro Shimizu |
890ddd |
globalImpSlots = new ExecutorImpSlots;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
qRegisterMetaType<tthread::runnablep>("TThread::RunnableP");</tthread::runnablep>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! This static method, which \b must be invoked in the controller thread, declares
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! by any Executor to quit as soon as possible in a safe way.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! \b NOTE: Observe that this method does not explicitly wait for all the tasks to terminate - this depends
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! remarks specified in started() signal descritpion); if this is the intent and the terminated slot
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! event processing is still performed) and wait there until the first finished() or catched()
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Executor::shutdown()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
shutdownVar = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::set<worker *="">::iterator it;</worker>
|
|
Toshihiro Shimizu |
890ddd |
for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); ++it) {
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = (*it)->m_task;
|
|
Toshihiro Shimizu |
890ddd |
if (task)
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->canceled(task);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutableMapIterator<int, runnablep=""> jt(globalImp->m_tasks);</int,>
|
|
Toshihiro Shimizu |
890ddd |
while (jt.hasNext()) {
|
|
Toshihiro Shimizu |
890ddd |
jt.next();
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = jt.value();
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->canceled(task);
|
|
Toshihiro Shimizu |
890ddd |
jt.remove();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); ++it) {
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = (*it)->m_task;
|
|
Toshihiro Shimizu |
890ddd |
if (task)
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->terminated(task);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//signals above are effectively invoked in this method - without having to return to an event loop.
|
|
Toshihiro Shimizu |
890ddd |
QCoreApplication::processEvents();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! try adoption of external tasks but instead remain focused on Executor's
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! An optional \b persistent parameter may be passed, which specifies if
|
|
Toshihiro Shimizu |
890ddd |
//! dedicated threads should remain sleeping or should rather die when no
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! This method is especially helpful in two occasions:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! The Executor's tasks use thread-specific data such as QThreadStorages,
|
|
Toshihiro Shimizu |
890ddd |
//! which may be recycled among different tasks.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Executor::setDedicatedThreads(bool dedicated, bool persistent)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_id->m_dedicatedThreads = dedicated;
|
|
Toshihiro Shimizu |
890ddd |
m_id->m_persistentThreads = persistent;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_id->refreshDedicatedList();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! its task load, insertion time and scheduling priority.
|
|
Toshihiro Shimizu |
890ddd |
void Executor::addTask(RunnableP task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (task->m_id)
|
|
Toshihiro Shimizu |
890ddd |
task->m_id->release();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Updating tasks and workers list - lock against state transitions
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
task->m_id = m_id;
|
|
Toshihiro Shimizu |
890ddd |
m_id->addRef();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->insertTask(task->schedulingPriority(), task);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImpSlots->emitRefreshAssignments();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! stopped by this method - although the canceled signal is still emitted.
|
|
Toshihiro Shimizu |
890ddd |
//! It has no effect if the task is not currently under the task manager's control.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Executor::removeTask(RunnableP task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (task->m_id != m_id)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Then, look in the global queue - if it is found, emiminate the task and
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (globalImp->m_tasks.remove(task->m_schedulingPriority, task)) {
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->canceled(task);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::set<worker *=""> &workers = globalImp->m_workers;</worker>
|
|
Toshihiro Shimizu |
890ddd |
std::set<worker *="">::iterator it;</worker>
|
|
Toshihiro Shimizu |
890ddd |
for (it = workers.begin(); it != workers.end(); ++it)
|
|
Toshihiro Shimizu |
890ddd |
if (task && (*it)->m_task == task)
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->canceled(task);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Clears the task manager of all tasks added by this Executor and emits
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Executor::cancelAll()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::set<worker *="">::iterator it;</worker>
|
|
Toshihiro Shimizu |
890ddd |
for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); ++it) {
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = (*it)->m_task;
|
|
Toshihiro Shimizu |
890ddd |
if (task && task->m_id == m_id)
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->canceled(task);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//Finally, clear the global tasks list from all tasks inserted by this executor
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QMutableMapIterator<int, runnablep=""> jt(globalImp->m_tasks);</int,>
|
|
Toshihiro Shimizu |
890ddd |
while (jt.hasNext()) {
|
|
Toshihiro Shimizu |
890ddd |
jt.next();
|
|
Toshihiro Shimizu |
890ddd |
if (jt.value()->m_id == m_id) {
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = jt.value();
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT task->canceled(task);
|
|
Toshihiro Shimizu |
890ddd |
jt.remove();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! Declares that only a certain number of tasks added by this Executor
|
|
Toshihiro Shimizu |
890ddd |
//! may be processed simultaneously. The default is 1 - meaning that tasks
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! \b NOTE: Currently, tasks that do not
|
|
Toshihiro Shimizu |
890ddd |
//! satisfy this condition avoid blocking execution of tasks not
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void Executor::setMaxActiveTasks(int maxActiveTasks)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (maxActiveTasks <= 0)
|
|
Toshihiro Shimizu |
890ddd |
m_id->m_maxActiveTasks = (std::numeric_limits<int>::max)();</int>
|
|
Toshihiro Shimizu |
890ddd |
else
|
|
Toshihiro Shimizu |
890ddd |
m_id->m_maxActiveTasks = maxActiveTasks;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int Executor::maxActiveTasks() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
return m_id->m_maxActiveTasks;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! \b NOTE: The same remark for setMaxActiveTasks() holds here.
|
|
Toshihiro Shimizu |
890ddd |
void Executor::setMaxActiveLoad(int maxActiveLoad)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_id->m_maxActiveLoad = maxActiveLoad;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int Executor::maxActiveLoad() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
return m_id->m_maxActiveLoad;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImpSlots::ExecutorImpSlots()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
connect(this, SIGNAL(refreshAssignments()), this, SLOT(onRefreshAssignments()));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExecutorImpSlots::~ExecutorImpSlots()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExecutorImpSlots::emitRefreshAssignments()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Q_EMIT refreshAssignments();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExecutorImpSlots::onRefreshAssignments()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QMutexLocker transitionLocker(&globalImp->m_transitionMutex);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->refreshAssignments();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExecutorImpSlots::onTerminated()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
delete QObject::sender();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void ExecutorId::newWorker(RunnableP &task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Worker *worker;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_sleepings.size()) {
|
|
Toshihiro Shimizu |
890ddd |
worker = m_sleepings.front();
|
|
Toshihiro Shimizu |
890ddd |
m_sleepings.pop_front();
|
|
Toshihiro Shimizu |
890ddd |
worker->m_task = task;
|
|
Toshihiro Shimizu |
890ddd |
worker->updateCountsOnTake();
|
|
Toshihiro Shimizu |
890ddd |
worker->m_waitCondition.wakeOne();
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
worker = new Worker;
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_workers.insert(worker);
|
|
Toshihiro Shimizu |
890ddd |
QObject::connect(worker, SIGNAL(finished()), globalImpSlots, SLOT(onTerminated()));
|
|
Toshihiro Shimizu |
890ddd |
worker->m_task = task;
|
|
Toshihiro Shimizu |
890ddd |
worker->updateCountsOnTake();
|
|
Toshihiro Shimizu |
890ddd |
worker->start();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void Worker::adoptTask(RunnableP &task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_task = task;
|
|
Toshihiro Shimizu |
890ddd |
updateCountsOnTake();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// perche' e' l'unico caso in cui le custom conditions
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// * Se un thread dedicato non puo' prendere una task estranea, non e' detto
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// a) First look if there exist tasks with timedOut priority and if so
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// b) Then look for tasks in the id's accumulation queue
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExecutorImp::refreshAssignments()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_tasks.isEmpty())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(m_executorIdPool.size() == m_waitingFlagsPool.size());
|
|
Toshihiro Shimizu |
890ddd |
memset(&m_waitingFlagsPool.front(), 0, m_waitingFlagsPool.size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int e, executorsCount = m_executorIdPool.acquiredSize();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i, tasksCount = m_tasks.size();
|
|
Toshihiro Shimizu |
890ddd |
QMultiMap<int, runnablep="">::iterator it;</int,>
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0, e = 0, it = m_tasks.end() - 1; i < tasksCount && e < executorsCount; ++i,
|
|
Toshihiro Shimizu |
890ddd |
//std::cout<< "global tasks-refreshAss" << std::endl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = it.value();
|
|
Toshihiro Shimizu |
890ddd |
task->m_load = task->taskLoad();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
UCHAR &idWaitingForAnotherTask = m_waitingFlagsPool[task->m_id->m_id];
|
|
Toshihiro Shimizu |
890ddd |
if (idWaitingForAnotherTask)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!isExecutable(task))
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!task->customConditions()) {
|
|
Toshihiro Shimizu |
890ddd |
++e;
|
|
Toshihiro Shimizu |
890ddd |
idWaitingForAnotherTask = 1;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
task->m_id->newWorker(task);
|
|
Toshihiro Shimizu |
890ddd |
it = m_tasks.erase(it);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline bool Worker::canAdopt(const RunnableP &task)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return task->m_id->m_sleepings.size() == 0 &&
|
|
Toshihiro Shimizu |
890ddd |
(!m_master || (m_master.getPointer() == task->m_id));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void Worker::takeTask()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TSmartPointerT<executorid> oldId = m_task->m_id;</executorid>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_master = oldId->m_dedicatedThreads ? oldId : (TSmartPointerT<executorid>)0;</executorid>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_transitionMutex.unlock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_task = 0;
|
|
Toshihiro Shimizu |
890ddd |
oldId = TSmartPointerT<executorid>();</executorid>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImp->m_transitionMutex.lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tcg::indices_pool<> &executorIdPool = globalImp->m_executorIdPool;
|
|
Toshihiro Shimizu |
890ddd |
std::vector<uchar> &waitingFlagsPool = globalImp->m_waitingFlagsPool;</uchar>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(waitingFlagsPool.size() == globalImp->m_executorIdPool.size());
|
|
Toshihiro Shimizu |
890ddd |
memset(&waitingFlagsPool.front(), 0, waitingFlagsPool.size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int e, executorsCount = executorIdPool.acquiredSize();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i, tasksCount = globalImp->m_tasks.size();
|
|
Toshihiro Shimizu |
890ddd |
QMultiMap<int, runnablep="">::iterator it;</int,>
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0, e = 0, it = globalImp->m_tasks.end() - 1; i < tasksCount && e < executorsCount; ++i,
|
|
Toshihiro Shimizu |
890ddd |
//std::cout<< "global tasks-takeTask" << std::endl;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
RunnableP task = it.value();
|
|
Toshihiro Shimizu |
890ddd |
task->m_load = task->taskLoad();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
UCHAR &idWaitingForAnotherTask = waitingFlagsPool[task->m_id->m_id];
|
|
Toshihiro Shimizu |
890ddd |
if (idWaitingForAnotherTask)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!globalImp->isExecutable(task))
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!canAdopt(task)) {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImpSlots->emitRefreshAssignments();
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!task->customConditions()) {
|
|
Toshihiro Shimizu |
890ddd |
++e;
|
|
Toshihiro Shimizu |
890ddd |
idWaitingForAnotherTask = 1;
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
adoptTask(task);
|
|
Toshihiro Shimizu |
890ddd |
it = globalImp->m_tasks.erase(it);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
globalImpSlots->emitRefreshAssignments();
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|