diff --git a/3rdparty/qcoro/LICENSE.MIT b/3rdparty/qcoro/LICENSE.MIT new file mode 100644 index 00000000..e0da07fc --- /dev/null +++ b/3rdparty/qcoro/LICENSE.MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Daniel Vrátil + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/3rdparty/qcoro/core/qcorocore.h b/3rdparty/qcoro/core/qcorocore.h index 8d04ba4f..134b97be 100644 --- a/3rdparty/qcoro/core/qcorocore.h +++ b/3rdparty/qcoro/core/qcorocore.h @@ -4,7 +4,6 @@ #include "config.h" -//#include "iodevice.h" #include "qcoroiodevice.h" #if !defined(Q_OS_IOS) # include "qcoroprocess.h" @@ -13,6 +12,6 @@ #include "qcorotimer.h" #ifdef QCORO_QT_HAS_COMPAT_ABI - #include "future.h" + #include "qcorofuture.h" #endif diff --git a/3rdparty/qcoro/core/qcorofuture.h b/3rdparty/qcoro/core/qcorofuture.h index 397325bf..c12c0d89 100644 --- a/3rdparty/qcoro/core/qcorofuture.h +++ b/3rdparty/qcoro/core/qcorofuture.h @@ -31,7 +31,7 @@ private: return mFuture.isFinished() || mFuture.isCanceled(); } - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) { + void await_suspend(std::coroutine_handle<> awaitingCoroutine) { auto *watcher = new QFutureWatcher(); auto cb = [watcher, awaitingCoroutine]() mutable { watcher->deleteLater(); diff --git a/3rdparty/qcoro/core/qcoroiodevice.cpp b/3rdparty/qcoro/core/qcoroiodevice.cpp index b0daf977..34ea33ea 100644 --- a/3rdparty/qcoro/core/qcoroiodevice.cpp +++ b/3rdparty/qcoro/core/qcoroiodevice.cpp @@ -14,7 +14,7 @@ QCoroIODevice::OperationBase::OperationBase(QIODevice *device) : mDevice(device) {} -void QCoroIODevice::OperationBase::finish(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroIODevice::OperationBase::finish(std::coroutine_handle<> awaitingCoroutine) { QObject::disconnect(mConn); QObject::disconnect(mCloseConn); // Delayed trigger @@ -29,7 +29,7 @@ bool QCoroIODevice::ReadOperation::await_ready() const noexcept { mDevice->bytesAvailable() > 0; } -void QCoroIODevice::ReadOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroIODevice::ReadOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { Q_ASSERT(mDevice); mConn = QObject::connect(mDevice, &QIODevice::readyRead, std::bind(&ReadOperation::finish, this, awaitingCoroutine)); @@ -62,7 +62,7 @@ bool QCoroIODevice::WriteOperation::await_ready() const noexcept { return false; } -void QCoroIODevice::WriteOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroIODevice::WriteOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { Q_ASSERT(mDevice); mConn = QObject::connect(mDevice, &QIODevice::bytesWritten, [this, awaitingCoroutine](qint64 written) { diff --git a/3rdparty/qcoro/core/qcoroiodevice.h b/3rdparty/qcoro/core/qcoroiodevice.h index 3759acca..523c57c3 100644 --- a/3rdparty/qcoro/core/qcoroiodevice.h +++ b/3rdparty/qcoro/core/qcoroiodevice.h @@ -28,7 +28,7 @@ private: protected: explicit OperationBase(QIODevice *device); - virtual void finish(QCORO_STD::coroutine_handle<> awaitingCoroutine); + virtual void finish(std::coroutine_handle<> awaitingCoroutine); QPointer mDevice; QMetaObject::Connection mConn; @@ -44,7 +44,7 @@ protected: QCORO_DEFAULT_MOVE(ReadOperation) virtual bool await_ready() const noexcept; - virtual void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + virtual void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; QByteArray await_resume(); private: @@ -58,7 +58,7 @@ protected: QCORO_DEFAULT_MOVE(WriteOperation) bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; qint64 await_resume() noexcept; private: diff --git a/3rdparty/qcoro/core/qcoroprocess.cpp b/3rdparty/qcoro/core/qcoroprocess.cpp index ae16dc71..3b7c6b0e 100644 --- a/3rdparty/qcoro/core/qcoroprocess.cpp +++ b/3rdparty/qcoro/core/qcoroprocess.cpp @@ -16,7 +16,7 @@ bool QCoroProcess::WaitForStartedOperation::await_ready() const noexcept { return !mObj || mObj->state() == QProcess::Running; } -void QCoroProcess::WaitForStartedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroProcess::WaitForStartedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { mConn = QObject::connect(mObj, &QProcess::stateChanged, [this, awaitingCoroutine](auto newState) mutable { switch (newState) { @@ -44,7 +44,7 @@ bool QCoroProcess::WaitForFinishedOperation::await_ready() const noexcept { return !mObj || mObj->state() == QProcess::NotRunning; } -void QCoroProcess::WaitForFinishedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroProcess::WaitForFinishedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) { mConn = QObject::connect(mObj, qOverload(&QProcess::finished), std::bind(&WaitForFinishedOperation::resume, this, awaitingCoroutine)); startTimeoutTimer(awaitingCoroutine); diff --git a/3rdparty/qcoro/core/qcoroprocess.h b/3rdparty/qcoro/core/qcoroprocess.h index c18abdf5..2d25d4ba 100644 --- a/3rdparty/qcoro/core/qcoroprocess.h +++ b/3rdparty/qcoro/core/qcoroprocess.h @@ -24,7 +24,7 @@ class QCoroProcess : public QCoroIODevice { public: WaitForStartedOperation(QProcess *process, int timeout_msecs = 30'000); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; }; //! An Awaitable that suspends the coroutine until the process is finished. @@ -32,7 +32,7 @@ class QCoroProcess : public QCoroIODevice { public: WaitForFinishedOperation(QProcess *process, int timeout_msecs); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine); + void await_suspend(std::coroutine_handle<> awaitingCoroutine); }; public: diff --git a/3rdparty/qcoro/core/qcorosignal.h b/3rdparty/qcoro/core/qcorosignal.h index b0ce5522..02cf641d 100644 --- a/3rdparty/qcoro/core/qcorosignal.h +++ b/3rdparty/qcoro/core/qcorosignal.h @@ -51,7 +51,7 @@ public: return mObj.isNull(); } - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { mConn = QObject::connect( mObj, mFuncPtr, mObj, [this, awaitingCoroutine](auto &&...args) mutable { diff --git a/3rdparty/qcoro/core/qcorotimer.cpp b/3rdparty/qcoro/core/qcorotimer.cpp index 0204d8da..5f8951bc 100644 --- a/3rdparty/qcoro/core/qcorotimer.cpp +++ b/3rdparty/qcoro/core/qcorotimer.cpp @@ -19,7 +19,7 @@ bool QCoroTimer::WaitForTimeoutOperation::await_ready() const noexcept { return !mTimer || !mTimer->isActive(); } -void QCoroTimer::WaitForTimeoutOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroTimer::WaitForTimeoutOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) { if (mTimer && mTimer->isActive()) { mConn = QObject::connect(mTimer, &QTimer::timeout, [this, awaitingCoroutine]() mutable { QObject::disconnect(mConn); diff --git a/3rdparty/qcoro/core/qcorotimer.h b/3rdparty/qcoro/core/qcorotimer.h index 74fd3d5b..85ba26a4 100644 --- a/3rdparty/qcoro/core/qcorotimer.h +++ b/3rdparty/qcoro/core/qcorotimer.h @@ -22,7 +22,7 @@ private: explicit WaitForTimeoutOperation(QTimer &timer); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine); + void await_suspend(std::coroutine_handle<> awaitingCoroutine); void await_resume() const; private: QMetaObject::Connection mConn; diff --git a/3rdparty/qcoro/coroutine.h b/3rdparty/qcoro/coroutine.h index 2bfaeb02..a23714ab 100644 --- a/3rdparty/qcoro/coroutine.h +++ b/3rdparty/qcoro/coroutine.h @@ -3,15 +3,250 @@ // SPDX-License-Identifier: MIT #pragma once -#if defined(__clang__) -#include -#define QCORO_STD std::experimental -#elif defined(__GNUC__) || defined(_MSC_VER) + +#include + +// __cpp_lib_coroutine is not defined if the compiler doesn't support coroutines +// (__cpp_impl_coroutine), e.g. clang as of 13.0. +#if defined(__cpp_lib_coroutine) #include +#elif defined(__clang__) +// Implement our own header in a way that is compatible with the standard. +// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf + +#include // void_t +#include // size_t + +// Intrinsincs for Clang +// https://clang.llvm.org/docs/LanguageExtensions.html#c-coroutines-support-builtins +extern "C" { +void __builtin_coro_destroy(void *addr); +void __builtin_coro_resume(void *addr); +bool __builtin_coro_done(void *addr); +void* __builtin_coro_promise(void *addr, int alignment, bool from_promise); +void *__builtin_coro_noop(); +} + +// 17.12.1 Header synopsis +namespace std { + +// 17.12.2, coroutine traits +// (omitted, because we implement them in std::experimental namespace and import them into the std +// namespace). +// template +// struct coroutine_traits; + +// 17.12.3, coroutine traits +template +struct coroutine_handle; + +// 17.12.3.6, comparison operators +constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; +// constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; + +// 17.12.3.7, hash support +//template struct hash; +//template struct hash>; + +// 17.12.4, n-op- coroutines +struct noop_coroutine_promise; + +template<> +struct coroutine_handle; +using noop_coroutine_handle = coroutine_handle; +noop_coroutine_handle noop_coroutine() noexcept; + +// 17.12.5, trivial awaitables +struct suspend_never; +struct suspend_always; + +} // namespace std + + +// Implementation +namespace std { + +// Clang checks for std::experimental::coroutine_traits explicitly, so we must define the types +// in the experimental namespace. +namespace experimental { + +template +struct __coroutine_traits_base {}; + +template +struct __coroutine_traits_base> { + using promise_type = typename R::promise_type; +}; + + +// 17.12.2, coroutine traits + +template +struct coroutine_traits : __coroutine_traits_base {}; + + +// Clang requires that std::experimental::coroutine_handle is a class template +template +struct coroutine_handle : public std::coroutine_handle {}; + +} // namespace experimental + +// Import std::experimental::coroutine_traits into the std namespace +template +using coroutine_traits = std::experimental::coroutine_traits; + + +// 17.12.3, coroutine handle + +template<> +struct coroutine_handle { + // 17.12.3.1, construct/reset + constexpr coroutine_handle() noexcept {} + constexpr coroutine_handle(nullptr_t) noexcept {} + coroutine_handle &operator=(nullptr_t) noexcept { + m_ptr = nullptr; + return *this; + } + + // 17.12.3.2, export/import + constexpr void *address() const noexcept { + return m_ptr; + } + + static constexpr coroutine_handle from_address(void *addr) noexcept { + coroutine_handle handle; + handle.m_ptr = addr; + return handle; + } + + // 17.12.3.3, observers + constexpr explicit operator bool() const noexcept { + return m_ptr != nullptr; + } + bool done() const { + return __builtin_coro_done(m_ptr); + } + + // 17.12.3.4, resumption + void operator()() const { + resume(); + } + void resume() const { + __builtin_coro_resume(m_ptr); + } + void destroy() const { + __builtin_coro_destroy(m_ptr); + } + +protected: + void *m_ptr = nullptr; +}; + +template +struct coroutine_handle : public coroutine_handle<> { + // 17.12.3.1, construct, reset + using coroutine_handle<>::coroutine_handle; + static coroutine_handle from_promise(Promise &promise) { + coroutine_handle handle; + handle.m_ptr = __builtin_coro_promise(&promise, alignof(Promise), /* from-promise=*/ true); + return handle; + } + coroutine_handle &operator=(nullptr_t) noexcept { + this->m_ptr = nullptr; + return *this; + } + + // 17.12.3.2, export/import + static constexpr coroutine_handle from_address(void *addr) noexcept { + coroutine_handle handle; + handle.m_ptr = addr; + return handle; + } + + //17.12.3.5, promise access + Promise &promise() const { + return *reinterpret_cast( + __builtin_coro_promise(m_ptr, alignof(Promise), /*from-promise=*/false)); + } +}; + +// 17.12.3.6, comparison operators +constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept { + return x.address() == y.address(); +} + +//constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; + +// 17.12.4, no-op coroutines +struct noop_coroutine_promise {}; + +template<> +struct coroutine_handle; +using noop_coroutine_handle = coroutine_handle; + +template<> +struct coroutine_handle : public coroutine_handle<> { + // 17.12.4.2.1, observers + constexpr explicit operator bool() const noexcept { return true; } + constexpr bool done() const noexcept { return false; } + constexpr void operator()() const noexcept {} + constexpr void resume() const noexcept {} + constexpr void destroy() const noexcept {} + + noop_coroutine_promise &promise() const noexcept { + return *reinterpret_cast( + __builtin_coro_promise(__builtin_coro_noop(), + alignof(noop_coroutine_promise), false)); + } + +private: + coroutine_handle() noexcept + : coroutine_handle<>(from_address(__builtin_coro_noop())) {} + + friend noop_coroutine_handle noop_coroutine() noexcept; +}; + +inline noop_coroutine_handle noop_coroutine() noexcept { + return {}; +} + +// 17.12.5, trivial awaitables + +struct suspend_never { + constexpr bool await_ready() const noexcept { return true; } + constexpr void await_resume() const noexcept {} + constexpr void await_suspend(coroutine_handle<>) const noexcept {} +}; + +struct suspend_always { + constexpr bool await_ready() const noexcept { return false; } + constexpr void await_suspend(coroutine_handle<>) const noexcept {} + constexpr void await_resume() const noexcept {} +}; + +} // namespace std + +#else // defined(__clang__) +#pragma error "Current compiler does not support coroutines, or is not supported by QCoro." +#endif // defined(__cpp_lib_coroutine) + +// The QCORO_STD macro is no longer needed (with the code above), but keep it for backwards +// compatibility. +#ifdef QCORO_NO_DEPRECATED_QCOROSTD #define QCORO_STD std -#else -#pragma error "Current compiler doesn't support Coroutines." -#endif +#else // QCORO_NO_DEPRECATED_QCOROSTD +#ifdef _MSC_VER + #define _QCORO_STRINGIFY2(x) #x + #define _QCORO_STRINGIFY(x) _QCORO_STRINGIFY2(x) + #define QCORO_STD \ + __pragma(message(__FILE__ "(" _QCORO_STRINGIFY(__LINE__) ") QCORO_STD macro is deprecated, use regular 'std' namespace instead, or pass /DQCORO_NO_DEPRECATED_QCOROSTD to suppress this warning.")) \ + std +#else // GCC, clang + #define QCORO_STD \ + _Pragma("GCC warning \"QCORO_STD macro is deprecated, use regular 'std' namespace instead, or pass -DQCORO_NO_DEPRECATED_QCOROSTD to suppress this warning.\"") \ + std +#endif // _MSC_VER +#endif // QCORO_NO_DEPRECATED_QCOROSTD // Moc doesn't seem to understand something in the header... #ifndef Q_MOC_RUN @@ -25,7 +260,7 @@ namespace detail { template concept has_await_methods = requires(T t) { { t.await_ready() } -> std::same_as; - {t.await_suspend(std::declval>())}; + {t.await_suspend(std::declval>())}; {t.await_resume()}; }; @@ -48,4 +283,4 @@ concept Awaitable = detail::has_operator_coawait || } // namespace QCoro -#endif +#endif // Q_MOC_RUN diff --git a/3rdparty/qcoro/dbus/qcorodbuspendingcall.cpp b/3rdparty/qcoro/dbus/qcorodbuspendingcall.cpp index 9c66cd0c..b496330b 100644 --- a/3rdparty/qcoro/dbus/qcorodbuspendingcall.cpp +++ b/3rdparty/qcoro/dbus/qcorodbuspendingcall.cpp @@ -16,7 +16,7 @@ bool QCoroDBusPendingCall::WaitForFinishedOperation::await_ready() const noexcep return mCall.isFinished(); } -void QCoroDBusPendingCall::WaitForFinishedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroDBusPendingCall::WaitForFinishedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { auto *watcher = new QDBusPendingCallWatcher{mCall}; QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [awaitingCoroutine](auto *watcher) mutable { diff --git a/3rdparty/qcoro/dbus/qcorodbuspendingcall.h b/3rdparty/qcoro/dbus/qcorodbuspendingcall.h index 97bff474..8054423a 100644 --- a/3rdparty/qcoro/dbus/qcorodbuspendingcall.h +++ b/3rdparty/qcoro/dbus/qcorodbuspendingcall.h @@ -22,7 +22,7 @@ private: explicit WaitForFinishedOperation(const QDBusPendingCall &call); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; QDBusMessage await_resume() const; private: const QDBusPendingCall &mCall; diff --git a/3rdparty/qcoro/dbus/qcorodbuspendingreply.h b/3rdparty/qcoro/dbus/qcorodbuspendingreply.h index 193d39dd..b314fa74 100644 --- a/3rdparty/qcoro/dbus/qcorodbuspendingreply.h +++ b/3rdparty/qcoro/dbus/qcorodbuspendingreply.h @@ -35,7 +35,7 @@ private: return mReply.isFinished(); } - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) { + void await_suspend(std::coroutine_handle<> awaitingCoroutine) { auto *watcher = new QDBusPendingCallWatcher{mReply}; QObject::connect(watcher, &QDBusPendingCallWatcher::finished, [awaitingCoroutine](auto *watcher) mutable { diff --git a/3rdparty/qcoro/network/qcoroabstractsocket.cpp b/3rdparty/qcoro/network/qcoroabstractsocket.cpp index eab70376..297cf043 100644 --- a/3rdparty/qcoro/network/qcoroabstractsocket.cpp +++ b/3rdparty/qcoro/network/qcoroabstractsocket.cpp @@ -15,7 +15,7 @@ bool QCoroAbstractSocket::WaitForConnectedOperation::await_ready() const noexcep return !mObj || mObj->state() == QAbstractSocket::ConnectedState; } -void QCoroAbstractSocket::WaitForConnectedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroAbstractSocket::WaitForConnectedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { mConn = QObject::connect(mObj, &QAbstractSocket::stateChanged, [this, awaitingCoroutine](auto newState) mutable { switch (newState) { @@ -46,7 +46,7 @@ bool QCoroAbstractSocket::WaitForDisconnectedOperation::await_ready() const noex return !mObj || mObj->state() == QAbstractSocket::UnconnectedState; } -void QCoroAbstractSocket::WaitForDisconnectedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept{ +void QCoroAbstractSocket::WaitForDisconnectedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept{ mConn = QObject::connect( mObj, &QAbstractSocket::disconnected, [this, awaitingCoroutine]() mutable { resume(awaitingCoroutine); }); @@ -59,7 +59,7 @@ bool QCoroAbstractSocket::ReadOperation::await_ready() const noexcept { QAbstractSocket::UnconnectedState; } -void QCoroAbstractSocket::ReadOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroAbstractSocket::ReadOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { QCoroIODevice::ReadOperation::await_suspend(awaitingCoroutine); mStateConn = QObject::connect( static_cast(mDevice.data()), &QAbstractSocket::stateChanged, @@ -71,7 +71,7 @@ void QCoroAbstractSocket::ReadOperation::await_suspend(QCORO_STD::coroutine_hand }); } -void QCoroAbstractSocket::ReadOperation::finish(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroAbstractSocket::ReadOperation::finish(std::coroutine_handle<> awaitingCoroutine) { QObject::disconnect(mStateConn); QCoroIODevice::ReadOperation::finish(awaitingCoroutine); } diff --git a/3rdparty/qcoro/network/qcoroabstractsocket.h b/3rdparty/qcoro/network/qcoroabstractsocket.h index 9885e082..fcb0081b 100644 --- a/3rdparty/qcoro/network/qcoroabstractsocket.h +++ b/3rdparty/qcoro/network/qcoroabstractsocket.h @@ -24,10 +24,10 @@ class QCoroAbstractSocket final : private QCoroIODevice { public: using QCoroIODevice::ReadOperation::ReadOperation; bool await_ready() const noexcept final; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept final; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept final; private: - void finish(QCORO_STD::coroutine_handle<> awaitingCoroutine); + void finish(std::coroutine_handle<> awaitingCoroutine); QMetaObject::Connection mStateConn; }; @@ -36,14 +36,14 @@ class QCoroAbstractSocket final : private QCoroIODevice { public: WaitForConnectedOperation(QAbstractSocket *socket, int timeout_msecs = 30'000); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; }; class WaitForDisconnectedOperation final : public WaitOperationBase { public: WaitForDisconnectedOperation(QAbstractSocket *socket, int timeout_msecs); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; }; public: diff --git a/3rdparty/qcoro/network/qcorolocalsocket.cpp b/3rdparty/qcoro/network/qcorolocalsocket.cpp index b1cb3652..8ffae3ab 100644 --- a/3rdparty/qcoro/network/qcorolocalsocket.cpp +++ b/3rdparty/qcoro/network/qcorolocalsocket.cpp @@ -19,7 +19,7 @@ bool QCoroLocalSocket::WaitForConnectedOperation::await_ready() const noexcept { return !mObj || mObj->state() == QLocalSocket::ConnectedState; } -void QCoroLocalSocket::WaitForConnectedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroLocalSocket::WaitForConnectedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { mConn = QObject::connect(mObj, &QLocalSocket::stateChanged, [this, awaitingCoroutine](auto newState) mutable { switch (newState) { @@ -48,7 +48,7 @@ bool QCoroLocalSocket::WaitForDisconnectedOperation::await_ready() const noexcep return !mObj || mObj->state() == QLocalSocket::UnconnectedState; } -void QCoroLocalSocket::WaitForDisconnectedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroLocalSocket::WaitForDisconnectedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) { mConn = QObject::connect(mObj, &QLocalSocket::disconnected, std::bind(&WaitForDisconnectedOperation::resume, this, awaitingCoroutine)); startTimeoutTimer(awaitingCoroutine); @@ -59,7 +59,7 @@ bool QCoroLocalSocket::ReadOperation::await_ready() const noexcept { static_cast(mDevice.data())->state() == QLocalSocket::UnconnectedState; } -void QCoroLocalSocket::ReadOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroLocalSocket::ReadOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { QCoroIODevice::ReadOperation::await_suspend(awaitingCoroutine); mStateConn = QObject::connect( static_cast(mDevice.data()), &QLocalSocket::stateChanged, @@ -70,7 +70,7 @@ void QCoroLocalSocket::ReadOperation::await_suspend(QCORO_STD::coroutine_handle< }); } -void QCoroLocalSocket::ReadOperation::finish(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroLocalSocket::ReadOperation::finish(std::coroutine_handle<> awaitingCoroutine) { QObject::disconnect(mStateConn); QCoroIODevice::ReadOperation::finish(awaitingCoroutine); } diff --git a/3rdparty/qcoro/network/qcorolocalsocket.h b/3rdparty/qcoro/network/qcorolocalsocket.h index 12d859fa..d1c9f62a 100644 --- a/3rdparty/qcoro/network/qcorolocalsocket.h +++ b/3rdparty/qcoro/network/qcorolocalsocket.h @@ -22,7 +22,7 @@ class QCoroLocalSocket : private QCoroIODevice { public: explicit WaitForConnectedOperation(QLocalSocket *socket, int timeout_msecs = 30'000); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; }; //! An Awaitable that suspends the coroutine until the socket is disconnected @@ -30,7 +30,7 @@ class QCoroLocalSocket : private QCoroIODevice { public: WaitForDisconnectedOperation(QLocalSocket *socket, int timeout_msecs); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine); + void await_suspend(std::coroutine_handle<> awaitingCoroutine); }; class ReadOperation final : public QCoroIODevice::ReadOperation { @@ -38,10 +38,10 @@ class QCoroLocalSocket : private QCoroIODevice { using QCoroIODevice::ReadOperation::ReadOperation; bool await_ready() const noexcept final; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept final; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept final; private: - void finish(QCORO_STD::coroutine_handle<> awaitingCoroutine) final; + void finish(std::coroutine_handle<> awaitingCoroutine) final; QMetaObject::Connection mStateConn; }; diff --git a/3rdparty/qcoro/network/qcoronetworkreply.cpp b/3rdparty/qcoro/network/qcoronetworkreply.cpp index 95536cce..a9e284ea 100644 --- a/3rdparty/qcoro/network/qcoronetworkreply.cpp +++ b/3rdparty/qcoro/network/qcoronetworkreply.cpp @@ -11,7 +11,7 @@ bool QCoroNetworkReply::ReadOperation::await_ready() const noexcept { static_cast(mDevice.data())->isFinished(); } -void QCoroNetworkReply::ReadOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroNetworkReply::ReadOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { QCoroIODevice::ReadOperation::await_suspend(awaitingCoroutine); mFinishedConn = QObject::connect( @@ -19,7 +19,7 @@ void QCoroNetworkReply::ReadOperation::await_suspend(QCORO_STD::coroutine_handle std::bind(&ReadOperation::finish, this, awaitingCoroutine)); } -void QCoroNetworkReply::ReadOperation::finish(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroNetworkReply::ReadOperation::finish(std::coroutine_handle<> awaitingCoroutine) { QObject::disconnect(mFinishedConn); QCoroIODevice::ReadOperation::finish(awaitingCoroutine); } @@ -32,7 +32,7 @@ bool QCoroNetworkReply::WaitForFinishedOperation::await_ready() const noexcept { return !mReply || mReply->isFinished(); } -void QCoroNetworkReply::WaitForFinishedOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) { +void QCoroNetworkReply::WaitForFinishedOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) { if (mReply) { QObject::connect(mReply, &QNetworkReply::finished, [awaitingCoroutine]() mutable { awaitingCoroutine.resume(); }); diff --git a/3rdparty/qcoro/network/qcoronetworkreply.h b/3rdparty/qcoro/network/qcoronetworkreply.h index 17ac577b..a0804dc7 100644 --- a/3rdparty/qcoro/network/qcoronetworkreply.h +++ b/3rdparty/qcoro/network/qcoronetworkreply.h @@ -19,10 +19,10 @@ private: using QCoroIODevice::ReadOperation::ReadOperation; bool await_ready() const noexcept final; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept final; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept final; private: - void finish(QCORO_STD::coroutine_handle<> awaitingCoroutine) final; + void finish(std::coroutine_handle<> awaitingCoroutine) final; QMetaObject::Connection mFinishedConn; }; @@ -32,7 +32,7 @@ private: explicit WaitForFinishedOperation(QPointer reply); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine); + void await_suspend(std::coroutine_handle<> awaitingCoroutine); QNetworkReply *await_resume() const noexcept; private: diff --git a/3rdparty/qcoro/network/qcorotcpserver.cpp b/3rdparty/qcoro/network/qcorotcpserver.cpp index e72c021f..e516f8b7 100644 --- a/3rdparty/qcoro/network/qcorotcpserver.cpp +++ b/3rdparty/qcoro/network/qcorotcpserver.cpp @@ -15,7 +15,7 @@ bool QCoroTcpServer::WaitForNewConnectionOperation::await_ready() const noexcept return !mObj || mObj->hasPendingConnections(); } -void QCoroTcpServer::WaitForNewConnectionOperation::await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { +void QCoroTcpServer::WaitForNewConnectionOperation::await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { mConn = QObject::connect(mObj, &QTcpServer::newConnection, std::bind(&WaitForNewConnectionOperation::resume, this, awaitingCoroutine)); startTimeoutTimer(awaitingCoroutine); diff --git a/3rdparty/qcoro/network/qcorotcpserver.h b/3rdparty/qcoro/network/qcorotcpserver.h index 2b23852d..7f27738f 100644 --- a/3rdparty/qcoro/network/qcorotcpserver.h +++ b/3rdparty/qcoro/network/qcorotcpserver.h @@ -24,7 +24,7 @@ class QCoroTcpServer { public: WaitForNewConnectionOperation(QTcpServer *server, int timeout_msecs = 30'000); bool await_ready() const noexcept; - void await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept; + void await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept; QTcpSocket *await_resume(); }; diff --git a/3rdparty/qcoro/qcoro.h b/3rdparty/qcoro/qcoro.h index b23158b9..5b113b97 100644 --- a/3rdparty/qcoro/qcoro.h +++ b/3rdparty/qcoro/qcoro.h @@ -4,30 +4,6 @@ #pragma once - -// vv workaround for QtCreator's clang code model warnings vv - -// Bypass GCC / MSVC coroutine guards when using clang code model -#if !defined(__APPLE__) && !defined(__ANDROID__) && (defined(__GNUC__) || defined(_MSC_VER)) -#if defined(__GNUC__) && defined(__clang__) && !defined(__cpp_impl_coroutine) -#define __cpp_impl_coroutine true -#elif defined(_MSC_VER) && defined(__clang__) && !defined(__cpp_lib_coroutine) -#define __cpp_lib_coroutine true -#endif -// Clang requires coroutine types in std::experimental -#include -#if defined(__clang__) -namespace std::experimental { -using std::coroutine_traits; -using std::coroutine_handle; -using std::suspend_always; -using std::suspend_never; -} -#endif -#endif - -// ^^ workaround for QtCreator's clang code model warnings ^^ - #include "task.h" #include "qcorocore.h" #if defined(QT_DBUS_LIB) diff --git a/3rdparty/qcoro/task.h b/3rdparty/qcoro/task.h index bc1b5ed1..5fed6af3 100644 --- a/3rdparty/qcoro/task.h +++ b/3rdparty/qcoro/task.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -39,7 +41,7 @@ public: * \param[in] awaitingCoroutine handle of the coroutine that is co_awaiting the current * coroutine (continuation). */ - explicit TaskFinalSuspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) + explicit TaskFinalSuspend(std::coroutine_handle<> awaitingCoroutine) : mAwaitingCoroutine(awaitingCoroutine) {} //! Returns whether the just finishing coroutine should do final suspend or not @@ -64,18 +66,16 @@ public: * \param[in] finishedCoroutine handle of the just finished coroutine */ template - void await_suspend(QCORO_STD::coroutine_handle<_Promise> finishedCoroutine) noexcept { + void await_suspend(std::coroutine_handle<_Promise> finishedCoroutine) noexcept { auto &promise = finishedCoroutine.promise(); - promise.mInFinalSuspend = true; - if (promise.mResumeAwaiter.exchange(true, std::memory_order_acq_rel)) { promise.mAwaitingCoroutine.resume(); } - if (promise.mDestroyOnFinalSuspend) { + + // The handle will be destroyed here only if the associated Task has already been destroyed + if (promise.setDestroyHandle()) { finishedCoroutine.destroy(); - } else { - promise.mInFinalSuspend = false; } } @@ -88,7 +88,7 @@ public: private: //! Handle of the coroutine co_awaiting the current coroutine. - QCORO_STD::coroutine_handle<> mAwaitingCoroutine; + std::coroutine_handle<> mAwaitingCoroutine; }; //! Base class for the \c Task promise_type. @@ -139,7 +139,7 @@ public: * it as a regular function, therefore it returns `std::suspend_never` awaitable, which * indicates that the coroutine should not be suspended. * */ - QCORO_STD::suspend_never initial_suspend() const noexcept { + std::suspend_never initial_suspend() const noexcept { return {}; } @@ -225,7 +225,7 @@ public: * represented by this promise. When our coroutine finishes, it's * our job to resume the awaiting coroutine. */ - bool setAwaitingCoroutine(QCORO_STD::coroutine_handle<> awaitingCoroutine) { + bool setAwaitingCoroutine(std::coroutine_handle<> awaitingCoroutine) { mAwaitingCoroutine = awaitingCoroutine; return !mResumeAwaiter.exchange(true, std::memory_order_acq_rel); } @@ -234,23 +234,20 @@ public: return mAwaitingCoroutine != nullptr; } - bool isInFinalSuspend() const { - return mInFinalSuspend; - } - - void setDestroyOnFinalSuspend() { - mDestroyOnFinalSuspend = true; + bool setDestroyHandle() noexcept { + return mDestroyHandle.exchange(true, std::memory_order_acq_rel); } private: friend class TaskFinalSuspend; //! Handle of the coroutine that is currently co_awaiting this Awaitable - QCORO_STD::coroutine_handle<> mAwaitingCoroutine; + std::coroutine_handle<> mAwaitingCoroutine; //! Indicates whether the awaiter should be resumed when it tries to co_await on us. std::atomic mResumeAwaiter{false}; - std::atomic mInFinalSuspend{false}; - std::atomic mDestroyOnFinalSuspend{false}; + + //! Indicates whether we can destroy the coroutine handle + std::atomic mDestroyHandle{false}; }; //! The promise_type for Task @@ -291,12 +288,12 @@ public: mValue = value; } - template requires QCoro::concepts::constructible_from + template requires concepts::constructible_from void return_value(U &&value) noexcept { mValue = std::move(value); } - template requires QCoro::concepts::constructible_from + template requires concepts::constructible_from void return_value(const U &value) noexcept { mValue = value; } @@ -308,6 +305,7 @@ public: */ T &result() & { if (std::holds_alternative(mValue)) { + Q_ASSERT(std::get(mValue) != nullptr); std::rethrow_exception(std::get(mValue)); } @@ -317,6 +315,7 @@ public: //! \copydoc T &QCoro::TaskPromise::result() & T &&result() && { if (std::holds_alternative(mValue)) { + Q_ASSERT(std::get(mValue) != nullptr); std::rethrow_exception(std::get(mValue)); } @@ -407,7 +406,7 @@ public: * co_awaited coroutine has finished synchronously and the co_awaiting coroutine doesn't * have to suspend. */ - bool await_suspend(QCORO_STD::coroutine_handle<> awaitingCoroutine) noexcept { + bool await_suspend(std::coroutine_handle<> awaitingCoroutine) noexcept { return mAwaitedCoroutine.promise().setAwaitingCoroutine(awaitingCoroutine); } @@ -416,11 +415,11 @@ protected: /*! * \param[in] coroutine hande for the coroutine that is being co_awaited. */ - TaskAwaiterBase(QCORO_STD::coroutine_handle<_Promise> awaitedCoroutine) + TaskAwaiterBase(std::coroutine_handle<_Promise> awaitedCoroutine) : mAwaitedCoroutine(awaitedCoroutine) {} //! Handle of the coroutine that is being co_awaited by this awaiter - QCORO_STD::coroutine_handle<_Promise> mAwaitedCoroutine = {}; + std::coroutine_handle<_Promise> mAwaitedCoroutine = {}; }; } // namespace detail @@ -459,7 +458,7 @@ public: /*! * \param[in] coroutine handle of the coroutine that has constructed the task. */ - explicit Task(QCORO_STD::coroutine_handle coroutine) : mCoroutine(coroutine) {} + explicit Task(std::coroutine_handle coroutine) : mCoroutine(coroutine) {} //! Task cannot be copy-constructed. Task(const Task &) = delete; @@ -475,7 +474,10 @@ public: Task &operator=(Task &&other) noexcept { if (std::addressof(other) != this) { if (mCoroutine) { - mCoroutine.destroy(); + // The coroutine handle will be destroyed only after TaskFinalSuspend + if (mCoroutine.promise().setDestroyHandle()) { + mCoroutine.destroy(); + } } mCoroutine = other.mCoroutine; @@ -486,13 +488,13 @@ public: //! Destructor. ~Task() { - if (mCoroutine) { - if (mCoroutine.done() && !mCoroutine.promise().isInFinalSuspend()) - mCoroutine.destroy(); - else - mCoroutine.promise().setDestroyOnFinalSuspend(); + if (!mCoroutine) return; + + // The coroutine handle will be destroyed only after TaskFinalSuspend + if (mCoroutine.promise().setDestroyHandle()) { + mCoroutine.destroy(); } - } + }; //! Returns whether the task has finished. /*! @@ -510,11 +512,11 @@ public: * object, that is an object that the co_await keyword uses to suspend and * resume the coroutine. */ - auto operator co_await() const &noexcept { + auto operator co_await() const noexcept { //! Specialization of the TaskAwaiterBase that returns the promise result by value class TaskAwaiter : public detail::TaskAwaiterBase { public: - TaskAwaiter(QCORO_STD::coroutine_handle awaitedCoroutine) + TaskAwaiter(std::coroutine_handle awaitedCoroutine) : detail::TaskAwaiterBase{awaitedCoroutine} {} //! Called when the co_awaited coroutine is resumed. @@ -523,36 +525,144 @@ public: * value co_returned by the coroutine. */ auto await_resume() { Q_ASSERT(this->mAwaitedCoroutine != nullptr); - return this->mAwaitedCoroutine.promise().result(); + if constexpr (!std::is_void_v) { + return std::move(this->mAwaitedCoroutine.promise().result()); + } else { + // Wil re-throw exception, if any is stored + this->mAwaitedCoroutine.promise().result(); + } } }; return TaskAwaiter{mCoroutine}; } - //! \copydoc QCoro::Task::operator co_await() const & noexcept - auto operator co_await() const &&noexcept { - //! Specialization of the TaskAwaiterBase that returns the promise result as an r-value reference. - class TaskAwaiter : public detail::TaskAwaiterBase { - public: - TaskAwaiter(QCORO_STD::coroutine_handle awaitedCoroutine) - : detail::TaskAwaiterBase{awaitedCoroutine} {} + //! A callback to be invoked when the asynchronous task finishes. + /*! + * In some scenarios it is not possible to co_await a coroutine (for example from + * a third-party code that cannot be changed to be a coroutine). In that case, + * chaining a then() callback is a possible solution how to handle a result + * of a coroutine without co_awaiting it. + * + * @param callback A function or a function object that can be invoked with a single + * argument of type T (that is type matching the return type of the coroutine). + * + * @return Returns Task where R is the return type of the callback, so that the + * result of the then() action can be co_awaited, if desired. If the callback + * returns an awaitable (Task) then the result of then is the awaitable. + */ + template + requires (std::is_void_v && std::invocable) || std::invocable + auto then(ThenCallback &&callback) { + return thenImpl(std::forward(callback)); + } - //! Called when the co_awaited coroutine is resumed. - /* - * \return an r-value reference to the coroutine's promise result, factically - * a value co_returned by the coroutine. */ - auto await_resume() { - Q_ASSERT(this->mAwaitedCoroutine != nullptr); - if constexpr (std::is_void_v) { - this->mAwaitedCoroutine.promise().result(); + template + requires (((std::is_void_v && std::invocable) || std::invocable) && + std::invocable) + auto then(ThenCallback &&callback, ErrorCallback &&errorCallback) { + return thenImpl(std::forward(callback), std::forward(errorCallback)); + } + +private: + template + struct invoke_result: std::invoke_result {}; + template + struct invoke_result: std::invoke_result {}; + template + using invoke_result_t = typename invoke_result::type; + + // Implementation of then() for callbacks that return Task + template> + requires QCoro::Awaitable + auto thenImpl(ThenCallback &&callback) -> R { + const auto cb = std::move(callback); + if constexpr (std::is_void_v) { + co_await *this; + co_return co_await cb(); + } else { + co_return co_await cb(co_await *this); + } + } + + template> + requires QCoro::Awaitable + auto thenImpl(ThenCallback &&thenCallback, ErrorCallback &&errorCallback) -> R { + const auto thenCb = std::move(thenCallback); + const auto errCb = std::move(errorCallback); + if constexpr (std::is_void_v) { + try { + co_await *this; + } catch (const std::exception &e) { + errCb(e); + if constexpr (!std::is_void_v) { + co_return {}; } else { - return std::move(this->mAwaitedCoroutine.promise().result()); + co_return; } } - }; + co_return co_await thenCb(); + } else { + std::optional v; + try { + v = co_await *this; + } catch (const std::exception &e) { + errCb(e); + if constexpr (!std::is_void_v) { + co_return {}; + } else { + co_return; + } + } + co_return co_await thenCb(std::move(*v)); + } + } - return TaskAwaiter{mCoroutine}; + + // Implementation of then() for callbacks that return R, which is not Task + template> + requires (!QCoro::Awaitable) + auto thenImpl(ThenCallback &&callback) -> Task { + const auto cb = std::move(callback); + if constexpr (std::is_void_v) { + co_await *this; + co_return cb(); + } else { + co_return cb(co_await *this); + } + } + + template> + requires (!QCoro::Awaitable) + auto thenImpl(ThenCallback &&thenCallback, ErrorCallback &&errorCallback) -> Task { + const auto thenCb = std::move(thenCallback); + const auto errCb = std::move(errorCallback); + if constexpr (std::is_void_v) { + try { + co_await *this; + } catch (const std::exception &e) { + errCb(e); + if constexpr (!std::is_void_v) { + co_return {}; + } else { + co_return; + } + } + co_return thenCb(); + } else { + std::optional v; + try { + v = co_await *this; + } catch (const std::exception &e) { + errCb(e); + if constexpr (!std::is_void_v) { + co_return {}; + } else { + co_return; + } + } + co_return thenCb(std::move(*v)); + } } private: @@ -561,18 +671,18 @@ private: * In other words, this is a handle to the coroutine that has constructed and * returned this Task. * */ - QCORO_STD::coroutine_handle mCoroutine = {}; + std::coroutine_handle mCoroutine = {}; }; namespace detail { template inline Task TaskPromise::get_return_object() noexcept { - return Task{QCORO_STD::coroutine_handle::from_promise(*this)}; + return Task{std::coroutine_handle::from_promise(*this)}; } Task inline TaskPromise::get_return_object() noexcept { - return Task{QCORO_STD::coroutine_handle::from_promise(*this)}; + return Task{std::coroutine_handle::from_promise(*this)}; } } // namespace detail diff --git a/3rdparty/qcoro/waitoperationbase_p.h b/3rdparty/qcoro/waitoperationbase_p.h index 80fd08f3..0adb585d 100644 --- a/3rdparty/qcoro/waitoperationbase_p.h +++ b/3rdparty/qcoro/waitoperationbase_p.h @@ -34,7 +34,7 @@ protected: } } - void startTimeoutTimer(QCORO_STD::coroutine_handle<> awaitingCoroutine) { + void startTimeoutTimer(std::coroutine_handle<> awaitingCoroutine) { if (!mTimeoutTimer) { return; } @@ -47,7 +47,7 @@ protected: mTimeoutTimer->start(); } - void resume(QCORO_STD::coroutine_handle<> awaitingCoroutine) { + void resume(std::coroutine_handle<> awaitingCoroutine) { if (mTimeoutTimer) { mTimeoutTimer->stop(); }