mirror of
https://github.com/rgriebl/brickstore.git
synced 2026-02-13 20:29:07 -06:00
Update 3rdparty/qcoro
This commit is contained in:
21
3rdparty/qcoro/LICENSE.MIT
vendored
Normal file
21
3rdparty/qcoro/LICENSE.MIT
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Daniel Vrátil <dvratil@kde.org>
|
||||
|
||||
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.
|
||||
3
3rdparty/qcoro/core/qcorocore.h
vendored
3
3rdparty/qcoro/core/qcorocore.h
vendored
@@ -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
|
||||
|
||||
|
||||
2
3rdparty/qcoro/core/qcorofuture.h
vendored
2
3rdparty/qcoro/core/qcorofuture.h
vendored
@@ -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<T_>();
|
||||
auto cb = [watcher, awaitingCoroutine]() mutable {
|
||||
watcher->deleteLater();
|
||||
|
||||
6
3rdparty/qcoro/core/qcoroiodevice.cpp
vendored
6
3rdparty/qcoro/core/qcoroiodevice.cpp
vendored
@@ -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) {
|
||||
|
||||
6
3rdparty/qcoro/core/qcoroiodevice.h
vendored
6
3rdparty/qcoro/core/qcoroiodevice.h
vendored
@@ -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<QIODevice> 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:
|
||||
|
||||
4
3rdparty/qcoro/core/qcoroprocess.cpp
vendored
4
3rdparty/qcoro/core/qcoroprocess.cpp
vendored
@@ -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<int, QProcess::ExitStatus>(&QProcess::finished),
|
||||
std::bind(&WaitForFinishedOperation::resume, this, awaitingCoroutine));
|
||||
startTimeoutTimer(awaitingCoroutine);
|
||||
|
||||
4
3rdparty/qcoro/core/qcoroprocess.h
vendored
4
3rdparty/qcoro/core/qcoroprocess.h
vendored
@@ -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:
|
||||
|
||||
2
3rdparty/qcoro/core/qcorosignal.h
vendored
2
3rdparty/qcoro/core/qcorosignal.h
vendored
@@ -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 {
|
||||
|
||||
2
3rdparty/qcoro/core/qcorotimer.cpp
vendored
2
3rdparty/qcoro/core/qcorotimer.cpp
vendored
@@ -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);
|
||||
|
||||
2
3rdparty/qcoro/core/qcorotimer.h
vendored
2
3rdparty/qcoro/core/qcorotimer.h
vendored
@@ -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;
|
||||
|
||||
253
3rdparty/qcoro/coroutine.h
vendored
253
3rdparty/qcoro/coroutine.h
vendored
@@ -3,15 +3,250 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
#if defined(__clang__)
|
||||
#include <experimental/coroutine>
|
||||
#define QCORO_STD std::experimental
|
||||
#elif defined(__GNUC__) || defined(_MSC_VER)
|
||||
|
||||
#include <version>
|
||||
|
||||
// __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 <coroutine>
|
||||
#elif defined(__clang__)
|
||||
// Implement our own <coroutine> 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 <type_traits> // void_t
|
||||
#include <cstddef> // 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 <coroutine> 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<class R, class .. ArgTypes>
|
||||
// struct coroutine_traits;
|
||||
|
||||
// 17.12.3, coroutine traits
|
||||
template<class Promise = void>
|
||||
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<class T> struct hash;
|
||||
//template<class P> struct hash<coroutine_handle<P>>;
|
||||
|
||||
// 17.12.4, n-op- coroutines
|
||||
struct noop_coroutine_promise;
|
||||
|
||||
template<>
|
||||
struct coroutine_handle<noop_coroutine_promise>;
|
||||
using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
|
||||
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<class R, class = void>
|
||||
struct __coroutine_traits_base {};
|
||||
|
||||
template<class R>
|
||||
struct __coroutine_traits_base<R, void_t<typename R::promise_type>> {
|
||||
using promise_type = typename R::promise_type;
|
||||
};
|
||||
|
||||
|
||||
// 17.12.2, coroutine traits
|
||||
|
||||
template<class R, class ... ArgTypes>
|
||||
struct coroutine_traits : __coroutine_traits_base<R> {};
|
||||
|
||||
|
||||
// Clang requires that std::experimental::coroutine_handle is a class template
|
||||
template<typename Promise>
|
||||
struct coroutine_handle : public std::coroutine_handle<Promise> {};
|
||||
|
||||
} // namespace experimental
|
||||
|
||||
// Import std::experimental::coroutine_traits into the std namespace
|
||||
template<typename R, typename ... ArgTypes>
|
||||
using coroutine_traits = std::experimental::coroutine_traits<R, ArgTypes ...>;
|
||||
|
||||
|
||||
// 17.12.3, coroutine handle
|
||||
|
||||
template<>
|
||||
struct coroutine_handle<void> {
|
||||
// 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<class Promise>
|
||||
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<Promise *>(
|
||||
__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<noop_coroutine_promise>;
|
||||
using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
|
||||
|
||||
template<>
|
||||
struct coroutine_handle<noop_coroutine_promise> : 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<noop_coroutine_promise *>(
|
||||
__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 <concepts> header...
|
||||
#ifndef Q_MOC_RUN
|
||||
@@ -25,7 +260,7 @@ namespace detail {
|
||||
template<typename T>
|
||||
concept has_await_methods = requires(T t) {
|
||||
{ t.await_ready() } -> std::same_as<bool>;
|
||||
{t.await_suspend(std::declval<QCORO_STD::coroutine_handle<>>())};
|
||||
{t.await_suspend(std::declval<std::coroutine_handle<>>())};
|
||||
{t.await_resume()};
|
||||
};
|
||||
|
||||
@@ -48,4 +283,4 @@ concept Awaitable = detail::has_operator_coawait<T> ||
|
||||
|
||||
} // namespace QCoro
|
||||
|
||||
#endif
|
||||
#endif // Q_MOC_RUN
|
||||
|
||||
2
3rdparty/qcoro/dbus/qcorodbuspendingcall.cpp
vendored
2
3rdparty/qcoro/dbus/qcorodbuspendingcall.cpp
vendored
@@ -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 {
|
||||
|
||||
2
3rdparty/qcoro/dbus/qcorodbuspendingcall.h
vendored
2
3rdparty/qcoro/dbus/qcorodbuspendingcall.h
vendored
@@ -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;
|
||||
|
||||
2
3rdparty/qcoro/dbus/qcorodbuspendingreply.h
vendored
2
3rdparty/qcoro/dbus/qcorodbuspendingreply.h
vendored
@@ -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 {
|
||||
|
||||
@@ -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<QAbstractSocket *>(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);
|
||||
}
|
||||
|
||||
8
3rdparty/qcoro/network/qcoroabstractsocket.h
vendored
8
3rdparty/qcoro/network/qcoroabstractsocket.h
vendored
@@ -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<QAbstractSocket> {
|
||||
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:
|
||||
|
||||
8
3rdparty/qcoro/network/qcorolocalsocket.cpp
vendored
8
3rdparty/qcoro/network/qcorolocalsocket.cpp
vendored
@@ -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<const QLocalSocket *>(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<QLocalSocket *>(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);
|
||||
}
|
||||
|
||||
8
3rdparty/qcoro/network/qcorolocalsocket.h
vendored
8
3rdparty/qcoro/network/qcorolocalsocket.h
vendored
@@ -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;
|
||||
};
|
||||
|
||||
6
3rdparty/qcoro/network/qcoronetworkreply.cpp
vendored
6
3rdparty/qcoro/network/qcoronetworkreply.cpp
vendored
@@ -11,7 +11,7 @@ bool QCoroNetworkReply::ReadOperation::await_ready() const noexcept {
|
||||
static_cast<const QNetworkReply *>(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(); });
|
||||
|
||||
6
3rdparty/qcoro/network/qcoronetworkreply.h
vendored
6
3rdparty/qcoro/network/qcoronetworkreply.h
vendored
@@ -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<QNetworkReply> 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:
|
||||
|
||||
2
3rdparty/qcoro/network/qcorotcpserver.cpp
vendored
2
3rdparty/qcoro/network/qcorotcpserver.cpp
vendored
@@ -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);
|
||||
|
||||
2
3rdparty/qcoro/network/qcorotcpserver.h
vendored
2
3rdparty/qcoro/network/qcorotcpserver.h
vendored
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
24
3rdparty/qcoro/qcoro.h
vendored
24
3rdparty/qcoro/qcoro.h
vendored
@@ -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 <coroutine>
|
||||
#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)
|
||||
|
||||
222
3rdparty/qcoro/task.h
vendored
222
3rdparty/qcoro/task.h
vendored
@@ -10,6 +10,8 @@
|
||||
#include <atomic>
|
||||
#include <variant>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QEventLoop>
|
||||
@@ -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<typename _Promise>
|
||||
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<T> 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<bool> mResumeAwaiter{false};
|
||||
std::atomic<bool> mInFinalSuspend{false};
|
||||
std::atomic<bool> mDestroyOnFinalSuspend{false};
|
||||
|
||||
//! Indicates whether we can destroy the coroutine handle
|
||||
std::atomic<bool> mDestroyHandle{false};
|
||||
};
|
||||
|
||||
//! The promise_type for Task<T>
|
||||
@@ -291,12 +288,12 @@ public:
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
template<typename U> requires QCoro::concepts::constructible_from<T, U>
|
||||
template<typename U> requires concepts::constructible_from<T, U>
|
||||
void return_value(U &&value) noexcept {
|
||||
mValue = std::move(value);
|
||||
}
|
||||
|
||||
template<typename U> requires QCoro::concepts::constructible_from<T, U>
|
||||
template<typename U> requires concepts::constructible_from<T, U>
|
||||
void return_value(const U &value) noexcept {
|
||||
mValue = value;
|
||||
}
|
||||
@@ -308,6 +305,7 @@ public:
|
||||
*/
|
||||
T &result() & {
|
||||
if (std::holds_alternative<std::exception_ptr>(mValue)) {
|
||||
Q_ASSERT(std::get<std::exception_ptr>(mValue) != nullptr);
|
||||
std::rethrow_exception(std::get<std::exception_ptr>(mValue));
|
||||
}
|
||||
|
||||
@@ -317,6 +315,7 @@ public:
|
||||
//! \copydoc T &QCoro::TaskPromise<T>::result() &
|
||||
T &&result() && {
|
||||
if (std::holds_alternative<std::exception_ptr>(mValue)) {
|
||||
Q_ASSERT(std::get<std::exception_ptr>(mValue) != nullptr);
|
||||
std::rethrow_exception(std::get<std::exception_ptr>(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<promise_type> coroutine) : mCoroutine(coroutine) {}
|
||||
explicit Task(std::coroutine_handle<promise_type> 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<promise_type> {
|
||||
public:
|
||||
TaskAwaiter(QCORO_STD::coroutine_handle<promise_type> awaitedCoroutine)
|
||||
TaskAwaiter(std::coroutine_handle<promise_type> awaitedCoroutine)
|
||||
: detail::TaskAwaiterBase<promise_type>{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<T>) {
|
||||
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<promise_type> {
|
||||
public:
|
||||
TaskAwaiter(QCORO_STD::coroutine_handle<promise_type> awaitedCoroutine)
|
||||
: detail::TaskAwaiterBase<promise_type>{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<R> 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<R>) then the result of then is the awaitable.
|
||||
*/
|
||||
template<typename ThenCallback>
|
||||
requires (std::is_void_v<T> && std::invocable<ThenCallback>) || std::invocable<ThenCallback, T>
|
||||
auto then(ThenCallback &&callback) {
|
||||
return thenImpl(std::forward<ThenCallback>(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<T>) {
|
||||
this->mAwaitedCoroutine.promise().result();
|
||||
template<typename ThenCallback, typename ErrorCallback>
|
||||
requires (((std::is_void_v<T> && std::invocable<ThenCallback>) || std::invocable<ThenCallback, T>) &&
|
||||
std::invocable<ErrorCallback, const std::exception &>)
|
||||
auto then(ThenCallback &&callback, ErrorCallback &&errorCallback) {
|
||||
return thenImpl(std::forward<ThenCallback>(callback), std::forward<ErrorCallback>(errorCallback));
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename ThenCallback, typename Arg = T>
|
||||
struct invoke_result: std::invoke_result<ThenCallback, T> {};
|
||||
template<typename ThenCallback>
|
||||
struct invoke_result<ThenCallback, void>: std::invoke_result<ThenCallback> {};
|
||||
template<typename ThenCallback, typename Arg>
|
||||
using invoke_result_t = typename invoke_result<ThenCallback, Arg>::type;
|
||||
|
||||
// Implementation of then() for callbacks that return Task<R>
|
||||
template<typename ThenCallback, typename R = invoke_result_t<ThenCallback, T>>
|
||||
requires QCoro::Awaitable<R>
|
||||
auto thenImpl(ThenCallback &&callback) -> R {
|
||||
const auto cb = std::move(callback);
|
||||
if constexpr (std::is_void_v<value_type>) {
|
||||
co_await *this;
|
||||
co_return co_await cb();
|
||||
} else {
|
||||
co_return co_await cb(co_await *this);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ThenCallback, typename ErrorCallback, typename R = invoke_result_t<ThenCallback, T>>
|
||||
requires QCoro::Awaitable<R>
|
||||
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<value_type>) {
|
||||
try {
|
||||
co_await *this;
|
||||
} catch (const std::exception &e) {
|
||||
errCb(e);
|
||||
if constexpr (!std::is_void_v<typename R::value_type>) {
|
||||
co_return {};
|
||||
} else {
|
||||
return std::move(this->mAwaitedCoroutine.promise().result());
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
};
|
||||
co_return co_await thenCb();
|
||||
} else {
|
||||
std::optional<T> v;
|
||||
try {
|
||||
v = co_await *this;
|
||||
} catch (const std::exception &e) {
|
||||
errCb(e);
|
||||
if constexpr (!std::is_void_v<typename R::value_type>) {
|
||||
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<S>
|
||||
template<typename ThenCallback, typename R = invoke_result_t<ThenCallback, T>>
|
||||
requires (!QCoro::Awaitable<R>)
|
||||
auto thenImpl(ThenCallback &&callback) -> Task<R> {
|
||||
const auto cb = std::move(callback);
|
||||
if constexpr (std::is_void_v<value_type>) {
|
||||
co_await *this;
|
||||
co_return cb();
|
||||
} else {
|
||||
co_return cb(co_await *this);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ThenCallback, typename ErrorCallback, typename R = invoke_result_t<ThenCallback, T>>
|
||||
requires (!QCoro::Awaitable<R>)
|
||||
auto thenImpl(ThenCallback &&thenCallback, ErrorCallback &&errorCallback) -> Task<R> {
|
||||
const auto thenCb = std::move(thenCallback);
|
||||
const auto errCb = std::move(errorCallback);
|
||||
if constexpr (std::is_void_v<value_type>) {
|
||||
try {
|
||||
co_await *this;
|
||||
} catch (const std::exception &e) {
|
||||
errCb(e);
|
||||
if constexpr (!std::is_void_v<R>) {
|
||||
co_return {};
|
||||
} else {
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
co_return thenCb();
|
||||
} else {
|
||||
std::optional<T> v;
|
||||
try {
|
||||
v = co_await *this;
|
||||
} catch (const std::exception &e) {
|
||||
errCb(e);
|
||||
if constexpr (!std::is_void_v<R>) {
|
||||
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<T>.
|
||||
* */
|
||||
QCORO_STD::coroutine_handle<promise_type> mCoroutine = {};
|
||||
std::coroutine_handle<promise_type> mCoroutine = {};
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline Task<T> TaskPromise<T>::get_return_object() noexcept {
|
||||
return Task<T>{QCORO_STD::coroutine_handle<TaskPromise>::from_promise(*this)};
|
||||
return Task<T>{std::coroutine_handle<TaskPromise>::from_promise(*this)};
|
||||
}
|
||||
|
||||
Task<void> inline TaskPromise<void>::get_return_object() noexcept {
|
||||
return Task<void>{QCORO_STD::coroutine_handle<TaskPromise>::from_promise(*this)};
|
||||
return Task<void>{std::coroutine_handle<TaskPromise>::from_promise(*this)};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
4
3rdparty/qcoro/waitoperationbase_p.h
vendored
4
3rdparty/qcoro/waitoperationbase_p.h
vendored
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user