Newer
Older
#include "MantidKernel/ThreadPoolRunnable.h"
#include "MantidKernel/System.h"
namespace Mantid
{
namespace Kernel
{
//-----------------------------------------------------------------------------------
/** Constructor
Janik Zikovsky
committed
*
* @param threadnum :: the thread ID that this runnable is running in.
* @param scheduler :: ThreadScheduler used by the thread pool
Janik Zikovsky
committed
* @param prog :: optional pointer to a Progress reporter object. If passed, then
* automatic progress reporting will be handled by the thread pool.
Janik Zikovsky
committed
* @param waitSec :: how many seconds the thread is allowed to wait with no tasks.
Janik Zikovsky
committed
ThreadPoolRunnable::ThreadPoolRunnable(size_t threadnum, ThreadScheduler * scheduler,
Janik Zikovsky
committed
ProgressBase * prog, double waitSec)
: m_threadnum(threadnum), m_scheduler(scheduler), m_prog(prog), m_waitSec(waitSec)
Janik Zikovsky
committed
if (!m_scheduler)
throw std::invalid_argument("NULL ThreadScheduler passed to ThreadPoolRunnable::ctor()");
}
//-----------------------------------------------------------------------------------
/** Destructor
*/
ThreadPoolRunnable::~ThreadPoolRunnable()
{}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------
/** Clear the wait time of the runnable so that it stops waiting for tasks. */
void ThreadPoolRunnable::clearWait()
{
m_waitSec = 0.0;
}
//-----------------------------------------------------------------------------------
/** Thread method. Will wait for new tasks and run them
* as scheduled to it.
*/
void ThreadPoolRunnable::run()
{
Task * task;
Janik Zikovsky
committed
// If there are no tasks yet, wait up to m_waitSec for them to come up
while (m_scheduler->size() == 0 && m_waitSec > 0.0)
{
Poco::Thread::sleep(10); // millisec
m_waitSec -= 0.01; // Subtract ten millisec from the time left to wait.
}
while (m_scheduler->size() > 0)
{
// Request the task from the scheduler.
// Will be NULL if not found.
task = m_scheduler->pop(m_threadnum);
if (task)
{
//Task-specific mutex if specified?
Mutex * mutex = task->getMutex();
if (mutex)
mutex->lock();
Janik Zikovsky
committed
try
{
// Run the task (synchronously within this thread)
task->run();
}
catch (std::exception &e)
{
// The task threw an exception!
// This will clear out the list of tasks, allowing all threads to finish.
m_scheduler->abort(std::runtime_error(e.what()));
}
Janik Zikovsky
committed
// Tell the scheduler that we finished this task
m_scheduler->finished(task, m_threadnum);
Janik Zikovsky
committed
// Report progress, if specified.
if (m_prog)
m_prog->report();
// Unlock the mutex, if any.
if (mutex)
mutex->unlock();
Janik Zikovsky
committed
// We now delete the task to free up memory
delete task;
}
else
{
// No appropriate task for this thread (perhaps a mutex is locked)
// but there are more tasks.
// So we wait a bit before checking again.
Janik Zikovsky
committed
Poco::Thread::sleep(10); // millisec