Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qfunctions_winrt_p.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QFUNCTIONS_WINRT_P_H
5#define QFUNCTIONS_WINRT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qglobal_p.h>
19
20#if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
21
22#include <QtCore/QCoreApplication>
23#include <QtCore/QThread>
24#include <QtCore/QAbstractEventDispatcher>
25#include <QtCore/QElapsedTimer>
26#include <QtCore/qt_windows.h>
27#include <QtCore/private/qcomptr_p.h>
28
29#include <windows.foundation.h>
30
31// Convenience macros for handling HRESULT values
32#define RETURN_IF_FAILED(msg, ret)
33 if (FAILED(hr)) {
34 qErrnoWarning(hr, msg);
35 ret;
36 }
37
38#define RETURN_IF_FAILED_WITH_ARGS(msg, ret, ...)
39 if (FAILED(hr)) {
40 qErrnoWarning(hr, msg, __VA_ARGS__);
41 ret;
42 }
43
44#define RETURN_HR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return hr)
45#define RETURN_OK_IF_FAILED(msg) RETURN_IF_FAILED(msg, return S_OK)
46#define RETURN_FALSE_IF_FAILED(msg) RETURN_IF_FAILED(msg, return false)
47#define RETURN_VOID_IF_FAILED(msg) RETURN_IF_FAILED(msg, return)
48#define RETURN_HR_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return hr, __VA_ARGS__)
49#define RETURN_OK_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return S_OK, __VA_ARGS__)
50#define RETURN_FALSE_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return false, __VA_ARGS__)
51#define RETURN_VOID_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return, __VA_ARGS__)
52
53#define Q_ASSERT_SUCCEEDED(hr)
54 Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
55
56QT_BEGIN_NAMESPACE
57
58namespace QWinRTFunctions {
59
60// Synchronization methods
61enum AwaitStyle
62{
63 YieldThread = 0,
64 ProcessThreadEvents = 1,
65 ProcessMainThreadEvents = 2
66};
67
68using EarlyExitConditionFunction = std::function<bool(void)>;
69
70template<typename T>
71static inline HRESULT _await_impl(const ComPtr<T> &asyncOp, AwaitStyle awaitStyle, uint timeout,
72 EarlyExitConditionFunction func)
73{
74 ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
75 HRESULT hr = asyncOp.As(&asyncInfo);
76 if (FAILED(hr))
77 return hr;
78
79 AsyncStatus status;
80 QElapsedTimer t;
81 if (timeout)
82 t.start();
83 switch (awaitStyle) {
84 case ProcessMainThreadEvents:
85 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
86 QCoreApplication::processEvents();
87 if (func && func())
88 return E_ABORT;
89 if (timeout && t.hasExpired(timeout))
90 return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
91 }
92 break;
93 case ProcessThreadEvents:
94 if (QAbstractEventDispatcher *dispatcher = QThread::currentThread()->eventDispatcher()) {
95 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
96 dispatcher->processEvents(QEventLoop::AllEvents);
97 if (func && func())
98 return E_ABORT;
99 if (timeout && t.hasExpired(timeout))
100 return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
101 }
102 break;
103 }
104 // fall through
105 default:
106 case YieldThread:
107 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
108 QThread::yieldCurrentThread();
109 if (timeout && t.hasExpired(timeout))
110 return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
111 }
112 break;
113 }
114
115 if (FAILED(hr) || status != AsyncStatus::Completed) {
116 HRESULT ec;
117 hr = asyncInfo->get_ErrorCode(&ec);
118 if (FAILED(hr))
119 return hr;
120 hr = asyncInfo->Close();
121 if (FAILED(hr))
122 return hr;
123 return ec;
124 }
125
126 return hr;
127}
128
129template<typename T>
130static inline HRESULT await(const ComPtr<T> &asyncOp, AwaitStyle awaitStyle = YieldThread,
131 uint timeout = 0, EarlyExitConditionFunction func = nullptr)
132{
133 HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout, func);
134 if (FAILED(hr))
135 return hr;
136
137 return asyncOp->GetResults();
138}
139
140template<typename T, typename U>
141static inline HRESULT await(const ComPtr<T> &asyncOp, U *results,
142 AwaitStyle awaitStyle = YieldThread, uint timeout = 0,
143 EarlyExitConditionFunction func = nullptr)
144{
145 HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout, func);
146 if (FAILED(hr))
147 return hr;
148
149 return asyncOp->GetResults(results);
150}
151
152} // QWinRTFunctions
153
154QT_END_NAMESPACE
155
156#endif // Q_OS_WIN && Q_CC_MSVC
157
158#endif // QFUNCTIONS_WINRT_P_H