diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-06-06 14:15:12 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@digia.com> | 2014-06-25 16:34:09 +0200 |
commit | 164ae66ff763b39cfe921df96470c7bfd11038d2 (patch) | |
tree | e6a2e3c388397b4356d4cb3a095152a773aff3b4 /src/corelib/kernel | |
parent | 6d95ce16493fbf819749dbd7ad9e8ffa61859cdb (diff) |
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 <maurice.kalinowski@digia.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qfunctions_winrt.h | 78 |
1 files changed, 78 insertions, 0 deletions
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 <QtCore/QThread> +#include <QtCore/QAbstractEventDispatcher> +#include <QtCore/qt_windows.h> + 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 <typename T> class ComPtr; } } + +namespace QWinRTFunctions { + +// Synchronization methods +enum AwaitStyle +{ + YieldThread = 0, + ProcessThreadEvents = 1, + ProcessMainThreadEvents = 2 +}; + +template <typename T> +static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle) +{ + Microsoft::WRL::ComPtr<IAsyncInfo> 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 <typename T> +static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle = YieldThread) +{ + HRESULT hr = _await_impl(asyncOp, awaitStyle); + if (FAILED(hr)) + return hr; + + return asyncOp->GetResults(); +} + +template <typename T, typename U> +static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &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 |