From 164ae66ff763b39cfe921df96470c7bfd11038d2 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Fri, 6 Jun 2014 14:15:12 +0300 Subject: winrt: Add convenience method for waiting on an async call As most of the Windows Runtime API is asynchronous, we have used various methods for blocking in the calling thread waiting for the operation to complete. This introduces an inline method, QWinRTFunctions::await(), which performs the wait in a consistent and safe manner. Task-number: QTBUG-39407 Change-Id: I54cd0e178aa560891ab92bfc5e7a6553e60e01b2 Reviewed-by: Maurice Kalinowski --- src/corelib/kernel/qfunctions_winrt.h | 78 +++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qfunctions_winrt.h b/src/corelib/kernel/qfunctions_winrt.h index 12488b6deb..5f051c3ea6 100644 --- a/src/corelib/kernel/qfunctions_winrt.h +++ b/src/corelib/kernel/qfunctions_winrt.h @@ -46,6 +46,10 @@ #ifdef Q_OS_WINRT +#include +#include +#include + QT_BEGIN_NAMESPACE #ifdef QT_BUILD_CORE_LIB @@ -133,5 +137,79 @@ generate_inline_return_func0(_tzset, void) #define Q_ASSERT_SUCCEEDED(hr) \ Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr))); + +namespace Microsoft { namespace WRL { template class ComPtr; } } + +namespace QWinRTFunctions { + +// Synchronization methods +enum AwaitStyle +{ + YieldThread = 0, + ProcessThreadEvents = 1, + ProcessMainThreadEvents = 2 +}; + +template +static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr &asyncOp, AwaitStyle awaitStyle) +{ + Microsoft::WRL::ComPtr asyncInfo; + HRESULT hr = asyncOp.As(&asyncInfo); + if (FAILED(hr)) + return hr; + + AsyncStatus status; + switch (awaitStyle) { + case ProcessMainThreadEvents: + while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started) + QCoreApplication::processEvents(); + break; + case ProcessThreadEvents: + if (QAbstractEventDispatcher *dispatcher = QThread::currentThread()->eventDispatcher()) { + while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started) + dispatcher->processEvents(QEventLoop::AllEvents); + break; + } + // fall through + default: + case YieldThread: + while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == Started) + QThread::yieldCurrentThread(); + break; + } + + if (FAILED(hr) || status != Completed) { + HRESULT ec; + hr = asyncInfo->get_ErrorCode(&ec); + if (FAILED(hr)) + return hr; + return ec; + } + + return hr; +} + +template +static inline HRESULT await(const Microsoft::WRL::ComPtr &asyncOp, AwaitStyle awaitStyle = YieldThread) +{ + HRESULT hr = _await_impl(asyncOp, awaitStyle); + if (FAILED(hr)) + return hr; + + return asyncOp->GetResults(); +} + +template +static inline HRESULT await(const Microsoft::WRL::ComPtr &asyncOp, U *results, AwaitStyle awaitStyle = YieldThread) +{ + HRESULT hr = _await_impl(asyncOp, awaitStyle); + if (FAILED(hr)) + return hr; + + return asyncOp->GetResults(results); +} + +} // QWinRTFunctions + #endif // Q_OS_WINRT #endif // QFUNCTIONS_WINRT_H -- cgit v1.2.3