diff --git a/base/Makefile.am b/base/Makefile.am index 56bebb664..824f5a61d 100644 --- a/base/Makefile.am +++ b/base/Makefile.am @@ -7,7 +7,6 @@ pkglib_LTLIBRARIES = \ libbase_la_SOURCES = \ application.cpp \ application.h \ - asynctask.cpp \ asynctask.h \ component.cpp \ component.h \ diff --git a/base/asynctask.cpp b/base/asynctask.cpp deleted file mode 100644 index c7c0ffe42..000000000 --- a/base/asynctask.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "i2-base.h" - -using namespace icinga; - -/** - * Constructor for the AsyncTaskBase class. - */ -AsyncTaskBase::AsyncTaskBase(void) - : m_Finished(false), m_ResultRetrieved(false) -{ } - -/** - * Destructor for the AsyncTaskBase class. - */ -AsyncTaskBase::~AsyncTaskBase(void) -{ - if (!m_Finished) { - Logger::Write(LogCritical, "base", "Contract violation: " - "AsyncTask was destroyed before its completion callback was invoked."); - } else if (!m_ResultRetrieved) { - Logger::Write(LogCritical, "base", "Contract violation: " - "AsyncTask was destroyed before its result was retrieved."); - } -} - -/** - * Starts the async task. The caller must hold a reference to the AsyncTask - * object until the completion callback is invoked. - */ -void AsyncTaskBase::Start(void) -{ - assert(Application::IsMainThread()); - - CallWithExceptionGuard(boost::bind(&AsyncTaskBase::Run, this)); -} - -/** - * Finishes the task using an exception. - * - * @param ex The exception. - */ -void AsyncTaskBase::Finish(const boost::exception_ptr& ex) -{ - m_Exception = ex; - - FinishInternal(); -} - -/** - * Finishes the task and causes the completion callback to be invoked. This - * function must be called before the object is destroyed. - */ -void AsyncTaskBase::FinishInternal(void) -{ - assert(!m_Finished); - - Event::Post(boost::bind(&AsyncTaskBase::InvokeCompletionCallback, - static_cast(GetSelf()))); -} - -/** - * Invokes the provided callback function and catches any exceptions it throws. - * Exceptions are stored into the task so that they can be re-thrown when the - * task owner calls GetResult(). - * - * @param task The task where exceptions should be saved. - * @param function The function that should be invoked. - * @returns true if no exception occured, false otherwise. - */ -bool AsyncTaskBase::CallWithExceptionGuard(function function) -{ - try { - function(); - - return true; - } catch (const exception&) { - Finish(boost::current_exception()); - - return false; - } -} diff --git a/base/asynctask.h b/base/asynctask.h index 4d42a49eb..304170a51 100644 --- a/base/asynctask.h +++ b/base/asynctask.h @@ -23,39 +23,13 @@ namespace icinga { -class I2_BASE_API AsyncTaskBase : public Object -{ -public: - typedef shared_ptr Ptr; - typedef weak_ptr WeakPtr; - - AsyncTaskBase(void); - ~AsyncTaskBase(void); - - void Start(void); - void Finish(const boost::exception_ptr& ex); - - bool CallWithExceptionGuard(function function); - -protected: - virtual void Run(void) = 0; - - virtual void InvokeCompletionCallback(void) = 0; - - void FinishInternal(void); - - bool m_Finished; /**< Whether the task is finished. */ - bool m_ResultRetrieved; /**< Whether the result was retrieved. */ - boost::exception_ptr m_Exception; -}; - /** * An asynchronous task. * * @ingroup base */ template -class AsyncTask : public AsyncTaskBase +class AsyncTask : public Object { public: typedef shared_ptr > Ptr; @@ -65,13 +39,39 @@ public: /** * Constructor for the AsyncTask class. - * - * @param completionCallback Function that is called when the task is completed. */ - AsyncTask(const CompletionCallback& completionCallback) - : m_CompletionCallback(completionCallback) + AsyncTask(void) + : m_Finished(false), m_ResultRetrieved(false) { } + /** + * Destructor for the AsyncTask class. + */ + ~AsyncTask(void) + { + if (!m_Finished) { + Logger::Write(LogCritical, "base", "Contract violation: " + "AsyncTask was destroyed before its completion callback was invoked."); + } else if (!m_ResultRetrieved) { + Logger::Write(LogCritical, "base", "Contract violation: " + "AsyncTask was destroyed before its result was retrieved."); + } + } + + + /** + * Starts the async task. The caller must hold a reference to the AsyncTask + * object until the completion callback is invoked. + */ + void Start(const CompletionCallback& completionCallback) + { + assert(Application::IsMainThread()); + + m_CompletionCallback = completionCallback; + + CallWithExceptionGuard(boost::bind(&AsyncTask::Run, this)); + } + /** * Retrieves the result of the task. Throws an exception if one is stored in * the AsyncTask object. @@ -89,21 +89,66 @@ public: if (m_Exception) boost::rethrow_exception(m_Exception); - return m_Result; + m_ResultRetrieved = true; + + TResult result; + std::swap(m_Result, result); + return result; } + /** + * Finishes the task using an exception. + * + * @param ex The exception. + */ + void Finish(const boost::exception_ptr& ex) + { + m_Exception = ex; + FinishInternal(); + } + + /** + * Finishes the task using an ordinary result. + * + * @param result The result. + */ void Finish(const TResult& result) { m_Result = result; FinishInternal(); } + /** + * Invokes the provided callback function and catches any exceptions it throws. + * Exceptions are stored into the task so that they can be re-thrown when the + * task owner calls GetResult(). + * + * @param task The task where exceptions should be saved. + * @param function The function that should be invoked. + * @returns true if no exception occured, false otherwise. + */ + bool CallWithExceptionGuard(function function) + { + try { + function(); + + return true; + } catch (const exception&) { + Finish(boost::current_exception()); + + return false; + } + } + +protected: + virtual void Run(void) = 0; + private: /** * Used by the Finish method to proxy the completion callback into the main * thread. Invokes the completion callback and marks the task as finished. */ - virtual void InvokeCompletionCallback(void) + void InvokeCompletionCallback(void) { m_Finished = true; m_CompletionCallback(GetSelf()); @@ -113,8 +158,23 @@ private: m_CompletionCallback = CompletionCallback(); } + /** + * Finishes the task and causes the completion callback to be invoked. This + * function must be called before the object is destroyed. + */ + void FinishInternal(void) + { + assert(!m_Finished); + + Event::Post(boost::bind(&AsyncTask::InvokeCompletionCallback, this)); + } + CompletionCallback m_CompletionCallback; /**< The completion callback. */ TResult m_Result; /**< The task's result. */ + boost::exception_ptr m_Exception; /**< The task's exception. */ + + bool m_Finished; /**< Whether the task is finished. */ + bool m_ResultRetrieved; /**< Whether the result was retrieved. */ }; } diff --git a/base/base.vcxproj b/base/base.vcxproj index 23b7ebdc2..216a75ff4 100644 --- a/base/base.vcxproj +++ b/base/base.vcxproj @@ -12,7 +12,6 @@ - diff --git a/base/base.vcxproj.filters b/base/base.vcxproj.filters index 771177581..4d4526411 100644 --- a/base/base.vcxproj.filters +++ b/base/base.vcxproj.filters @@ -85,9 +85,6 @@ Quelldateien - - Quelldateien - Quelldateien diff --git a/base/configobject.cpp b/base/configobject.cpp index bd4f56577..86a520c31 100644 --- a/base/configobject.cpp +++ b/base/configobject.cpp @@ -210,8 +210,8 @@ ScriptTask::Ptr ConfigObject::InvokeHook(const string& hook, if (!func) throw invalid_argument("Function '" + funcName + "' does not exist."); - ScriptTask::Ptr task = boost::make_shared(func, arguments, callback); - task->Start(); + ScriptTask::Ptr task = boost::make_shared(func, arguments); + task->Start(callback); return task; } diff --git a/base/i2-base.h b/base/i2-base.h index 5d875aeff..0d46d028c 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -167,6 +167,7 @@ using boost::system_time; #include "tcpclient.h" #include "tcpserver.h" #include "tlsclient.h" +#include "logger.h" #include "asynctask.h" #include "process.h" #include "scriptfunction.h" @@ -177,7 +178,6 @@ using boost::system_time; #include "application.h" #include "component.h" #include "threadpool.h" -#include "logger.h" #include "streamlogger.h" #include "sysloglogger.h" diff --git a/base/object.cpp b/base/object.cpp index ccc9ac171..334480467 100644 --- a/base/object.cpp +++ b/base/object.cpp @@ -27,15 +27,13 @@ vector Object::m_HeldObjects; * Default constructor for the Object class. */ Object::Object(void) -{ -} +{ } /** * Destructor for the Object class. */ Object::~Object(void) -{ -} +{ } /** * Temporarily holds onto a reference for an object. This can diff --git a/base/process.cpp b/base/process.cpp index 4232647d4..1c1146a30 100644 --- a/base/process.cpp +++ b/base/process.cpp @@ -30,8 +30,8 @@ boost::mutex Process::m_Mutex; deque Process::m_Tasks; condition_variable Process::m_TasksCV; -Process::Process(const string& command, const CompletionCallback& completionCallback) - : AsyncTask(completionCallback), m_Command(command), m_UsePopen(false) +Process::Process(const string& command) + : AsyncTask(), m_Command(command), m_UsePopen(false) { if (!m_ThreadCreated) { thread t(&Process::WorkerThreadProc); diff --git a/base/process.h b/base/process.h index 03623f8df..186f03a35 100644 --- a/base/process.h +++ b/base/process.h @@ -39,7 +39,7 @@ public: static const int MaxTasksPerThread = 128; - Process(const string& command, const CompletionCallback& completionCallback); + Process(const string& command); private: static bool m_ThreadCreated; diff --git a/base/scripttask.cpp b/base/scripttask.cpp index 1066729f7..ac9e87814 100644 --- a/base/scripttask.cpp +++ b/base/scripttask.cpp @@ -2,8 +2,8 @@ using namespace icinga; -ScriptTask::ScriptTask(const ScriptFunction::Ptr& function, const vector& arguments, CompletionCallback callback) - : AsyncTask(callback), m_Function(function), m_Arguments(arguments) +ScriptTask::ScriptTask(const ScriptFunction::Ptr& function, const vector& arguments) + : AsyncTask(), m_Function(function), m_Arguments(arguments) { } void ScriptTask::Run(void) diff --git a/base/scripttask.h b/base/scripttask.h index a3c933518..61913f281 100644 --- a/base/scripttask.h +++ b/base/scripttask.h @@ -29,7 +29,7 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - ScriptTask(const ScriptFunction::Ptr& function, const vector& arguments, CompletionCallback callback); + ScriptTask(const ScriptFunction::Ptr& function, const vector& arguments); protected: virtual void Run(void);