Implement AsyncTask::Wait() and make completion callbacks optional.

This commit is contained in:
Gunnar Beutner 2013-02-06 10:53:28 +01:00
parent 25e34fa5d2
commit 53705d16dc
5 changed files with 56 additions and 16 deletions

View File

@ -89,11 +89,32 @@ Application::Ptr Application::GetInstance(void)
return Application::Ptr();
}
/**
* Runs one iteration of the event loop.
*
* @returns false if we're shutting down, true otherwise.
*/
bool Application::ProcessEvents(void) const
{
Object::ClearHeldObjects();
double sleep = Timer::ProcessTimers();
if (m_ShuttingDown)
return false;
Event::ProcessEvents(boost::posix_time::milliseconds(sleep * 1000));
DynamicObject::FlushTx();
return true;
}
/**
* Processes events for registered sockets and timers and calls whatever
* handlers have been set up for these events.
*/
void Application::RunEventLoop(void)
void Application::RunEventLoop(void) const
{
#ifdef _DEBUG
double nextProfile = 0;
@ -104,17 +125,9 @@ void Application::RunEventLoop(void)
t.detach();
while (!m_ShuttingDown) {
Object::ClearHeldObjects();
double sleep = Timer::ProcessTimers();
if (m_ShuttingDown)
if (!ProcessEvents())
break;
Event::ProcessEvents(boost::posix_time::milliseconds(sleep * 1000));
DynamicObject::FlushTx();
#ifdef _DEBUG
if (nextProfile < Utility::GetTime()) {
stringstream msgbuf;

View File

@ -76,8 +76,10 @@ public:
static String GetPkgDataDir(void);
static void SetPkgDataDir(const String& path);
bool ProcessEvents(void) const;
protected:
void RunEventLoop(void);
void RunEventLoop(void) const;
private:
static Application *m_Instance; /**< The application instance. */

View File

@ -63,7 +63,7 @@ public:
* 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)
void Start(const CompletionCallback& completionCallback = CompletionCallback())
{
m_CompletionCallback = completionCallback;
@ -128,6 +128,14 @@ public:
FinishInternal();
}
/**
* Blocks until the task is completed.
*/
void Wait(void)
{
Utility::WaitUntil(boost::bind(&AsyncTask<TClass, TResult>::IsFinished, this));
}
protected:
/**
* Begins executing the task. The Run method must ensure
@ -146,11 +154,14 @@ private:
assert(!m_Finished);
m_Finished = true;
m_CompletionCallback(GetSelf());
/* Clear callback because the bound function might hold a
* reference to this task. */
m_CompletionCallback = CompletionCallback();
if (!m_CompletionCallback.empty()) {
m_CompletionCallback(GetSelf());
/* Clear callback because the bound function might hold a
* reference to this task. */
m_CompletionCallback = CompletionCallback();
}
}
CompletionCallback m_CompletionCallback; /**< The completion callback. */

View File

@ -499,3 +499,15 @@ bool Utility::Glob(const String& pathSpec, const function<void (const String&)>&
return true;
#endif /* _WIN32 */
}
/**
* Waits until the given predicate is true. Executes events while waiting.
*
* @param predicate The predicate.
*/
void Utility::WaitUntil(const function<bool (void)>& predicate)
{
while (!predicate)
Application::GetInstance()->ProcessEvents();
}

View File

@ -58,6 +58,8 @@ public:
static bool Glob(const String& pathSpec, const function<void (const String&)>& callback);
static void WaitUntil(const function<bool (void)>& predicate);
static
#ifdef _WIN32
HMODULE