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