1 /******************************************************************************
3 * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
27 * An asynchronous task.
31 template<typename TClass, typename TResult>
32 class AsyncTask : public Object
35 typedef shared_ptr<AsyncTask<TClass, TResult> > Ptr;
36 typedef weak_ptr<AsyncTask<TClass, TResult> > WeakPtr;
39 * A completion callback for an AsyncTask.
41 typedef function<void (const shared_ptr<TClass>&)> CompletionCallback;
44 * Constructor for the AsyncTask class.
47 : m_Finished(false), m_ResultRetrieved(false)
51 * Destructor for the AsyncTask class.
56 assert(!"Contract violation: AsyncTask was destroyed before its completion callback was invoked.");
57 else if (!m_ResultRetrieved)
58 assert(!"Contract violation: AsyncTask was destroyed before its result was retrieved.");
63 * Starts the async task. The caller must hold a reference to the AsyncTask
64 * object until the completion callback is invoked.
66 void Start(const CompletionCallback& completionCallback = CompletionCallback())
68 m_CompletionCallback = completionCallback;
73 FinishException(boost::current_exception());
78 * Checks whether the task is finished.
80 bool IsFinished(void) const
86 * Retrieves the result of the task. Throws an exception if one is stored in
87 * the AsyncTask object.
89 * @returns The task's result.
91 TResult GetResult(void)
94 BOOST_THROW_EXCEPTION(runtime_error("GetResult called on an unfinished AsyncTask"));
96 if (m_ResultRetrieved)
97 BOOST_THROW_EXCEPTION(runtime_error("GetResult called on an AsyncTask whose result was already retrieved."));
99 m_ResultRetrieved = true;
102 rethrow_exception(m_Exception);
105 std::swap(m_Result, result);
110 * Finishes the task using an exception.
112 * @param ex The exception.
114 void FinishException(const boost::exception_ptr& ex)
121 * Finishes the task using an ordinary result.
123 * @param result The result.
125 void FinishResult(const TResult& result)
132 * Blocks until the task is completed.
136 Utility::WaitUntil(boost::bind(&AsyncTask<TClass, TResult>::IsFinished, this));
141 * Begins executing the task. The Run method must ensure
142 * that one of the Finish*() functions is executed on the task
143 * object (possibly after the Run method has returned).
145 virtual void Run(void) = 0;
149 * Finishes the task and causes the completion callback to be invoked. This
150 * function must be called before the object is destroyed.
152 void FinishInternal(void)
158 if (!m_CompletionCallback.empty()) {
159 m_CompletionCallback(GetSelf());
161 /* Clear callback because the bound function might hold a
162 * reference to this task. */
163 m_CompletionCallback = CompletionCallback();
167 CompletionCallback m_CompletionCallback; /**< The completion callback. */
168 TResult m_Result; /**< The task's result. */
169 boost::exception_ptr m_Exception; /**< The task's exception. */
171 bool m_Finished; /**< Whether the task is finished. */
172 bool m_ResultRetrieved; /**< Whether the result was retrieved. */
177 #endif /* ASYNCTASK_H */