Permalink
Fetching contributors…
Cannot retrieve contributors at this time
156 lines (124 sloc) 3.14 KB
/*
Scan Tailor - Interactive post-processing tool for scanned pages.
Copyright (C) Joseph Artsimovich <joseph.artsimovich@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "BackgroundExecutor.h"
#include "OutOfMemoryHandler.h"
#include <QCoreApplication>
#include <QObject>
#include <QThread>
#include <QEvent>
#include <new>
#include <assert.h>
class BackgroundExecutor::Dispatcher : public QObject
{
public:
Dispatcher(Impl& owner);
protected:
virtual void customEvent(QEvent* event);
private:
Impl& m_rOwner;
};
class BackgroundExecutor::Impl : public QThread
{
public:
Impl(BackgroundExecutor& owner);
~Impl();
void enqueueTask(TaskPtr const& task);
protected:
virtual void run();
virtual void customEvent(QEvent* event);
private:
BackgroundExecutor& m_rOwner;
Dispatcher m_dispatcher;
bool m_threadStarted;
};
/*============================ BackgroundExecutor ==========================*/
BackgroundExecutor::BackgroundExecutor()
: m_ptrImpl(new Impl(*this))
{
}
BackgroundExecutor::~BackgroundExecutor()
{
}
void
BackgroundExecutor::shutdown()
{
m_ptrImpl.reset();
}
void
BackgroundExecutor::enqueueTask(TaskPtr const& task)
{
if (m_ptrImpl.get()) {
m_ptrImpl->enqueueTask(task);
}
}
/*===================== BackgroundExecutor::Dispatcher =====================*/
BackgroundExecutor::Dispatcher::Dispatcher(Impl& owner)
: m_rOwner(owner)
{
}
void
BackgroundExecutor::Dispatcher::customEvent(QEvent* event)
{
try {
TaskEvent* evt = dynamic_cast<TaskEvent*>(event);
assert(evt);
TaskPtr const& task = evt->payload();
assert(task);
TaskResultPtr const result((*task)());
if (result) {
QCoreApplication::postEvent(
&m_rOwner, new ResultEvent(result)
);
}
} catch (std::bad_alloc const&) {
OutOfMemoryHandler::instance().handleOutOfMemorySituation();
}
}
/*======================= BackgroundExecutor::Impl =========================*/
BackgroundExecutor::Impl::Impl(BackgroundExecutor& owner)
: m_rOwner(owner),
m_dispatcher(*this),
m_threadStarted(false)
{
m_dispatcher.moveToThread(this);
}
BackgroundExecutor::Impl::~Impl()
{
exit();
wait();
}
void
BackgroundExecutor::Impl::enqueueTask(TaskPtr const& task)
{
QCoreApplication::postEvent(&m_dispatcher, new TaskEvent(task));
if (!m_threadStarted) {
start();
m_threadStarted = true;
}
}
void
BackgroundExecutor::Impl::run()
{
exec();
}
void
BackgroundExecutor::Impl::customEvent(QEvent* event)
{
ResultEvent* evt = dynamic_cast<ResultEvent*>(event);
assert(evt);
TaskResultPtr const& result = evt->payload();
assert(result);
(*result)();
}