Code Monkey home page Code Monkey logo

qcoro's Introduction

Linux CI Windows CI MacOS CI Docs build Latest release License: MIT C++20 Supported Compilers

QCoro - Coroutines for Qt5 and Qt6

The QCoro library provides set of tools to make use of C++20 coroutines with Qt.

Take a look at the example below to see what an amazing thing coroutines are:

QNetworkAccessManager networkAccessManager;
// co_await the reply - the coroutine is suspended until the QNetworkReply is finished.
// While the coroutine is suspended, *the Qt event loop runs as usual*.
const QNetworkReply *reply = co_await networkAccessManager.get(url);
// Once the reply is finished, your code resumes here as if nothing amazing has just happened ;-)
const auto data = reply->readAll();

It requires a compiler with support for the couroutines TS.

Documentation

πŸ‘‰ πŸ“˜ Documentation

Supported Qt Types

QCoro provides QCoro::Task<T> which can be used as a coroutine return type and allows the coroutine to be awaited by its caller. Additionally, it provides qCoro() wrapper function, which wraps an object of a supported Qt type to a thin, coroutine-friendly wrapper that allows co_awaiting asynchronous operations on this type. Finally, it allows to directly co_await default asynchronous operations on certain Qt types. Below is a list of a few supported types, you can find the full list in the documentation.

QDBusPendingCall

QCoro can wait for an asynchronous D-Bus call to finish. There's no need to use QDBusPendingCallWatcher with QCoro - just co_await the result instead. While co_awaiting, the Qt event loop runs as usual.

QDBusInterface remoteServiceInterface{serviceName, objectPath, interface};
const QDBusReply<bool> isReady = co_await remoteServiceInterface.asyncCall(QStringLiteral("isReady"));

πŸ“˜ Full documentation here.

QFuture

QFuture represents a result of an asynchronous task. Normally you have to use QFutureWatcher to get notified when the future is ready. With QCoro, you can just co_await it!

const QFuture<int> task1 = QtConcurrent::run(....);
const QFuture<int> task2 = QtConcurrent::run(....);

const int a = co_await task1;
const int b = co_await task2;

co_return a + b;

πŸ“˜ Full documentation here.

QNetworkReply

Doing network requests with Qt can be tedious - the signal/slot approach breaks the flow of your code. Chaining requests and error handling quickly become mess and your code is broken into numerous functions. But not with QCoro, where you can simply co_await the QNetworkReply to finish:

QNetworkReply qnam;
QNetworkReply *reply = qnam.get(QStringLiteral("https://github.com/danvratil/qcoro"));
const auto contents = co_await reply;
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
    co_return handleError(reply);
}

const auto link = findLinkInReturnedHtmlCode(contents);
reply = qnam.get(link);
const auto data = co_await reply;
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
    co_return handleError(reply);
}
 ...

πŸ“˜ Full documentation here.

QTimer

Maybe you want to delay executing your code for a second, maybe you want to execute some code in repeated interval. This becomes super-trivial with co_await:

QTimer timer;
timer.setInterval(1s);
timer.start();

for (int i = 1; i <= 100; ++i) {
    co_await timer;
    qDebug() << "Waiting for " << i << " seconds...";
}

qDebug() << "Done!";

πŸ“˜ Full documentation here.

QIODevice

QIODevice is a base-class for many classes in Qt that allow data to be asynchronously written and read. How do you find out that there are data ready to be read? You could connect to QIODevice::readyRead() singal, or you could use QCoro and co_await the object:

socket->write("PING");
// Waiting for "pong"
const auto data = co_await socket;
co_return calculateLatency(data);

πŸ“˜ Full documentation here.

...and more!

Go check the full documentation to learn more.

.then() continuations

Sometimes it's not possible to use co_await to handle result of a coroutine - usually when interfacing with a 3rd party code that does not support coroutines. In those scenarios it's possible to chain a continuation callback to the coroutine which will get invoked asynchronously when the coroutine finishes.

void regularFunction() {
    someCoroutineReturningInt().then([](int result) {
        // handle result
    });
}

The continuation callback can also be a coroutine and the result of the entire expression is Task where T is the return type of the continuation. Thanks to that it's possible to co_await the entire chain, or chain multiple .then() continuations.

πŸ“˜ Full documentation here.

Generators

Generator is a coroutine that lazily produces multiple values. While there's nothing Qt-specific, QCoro provides the necessary tools for users to create custom generators in their Qt applications.

QCoro provides API for both synchronous generators (QCoro::Generator<T>) and asynchronous generators (QCoro::AsyncGenerator<T>). Both generators provide container-like API: begin() and end() member functions that return iterator-like objects, which is well-known and established API and makes generators compatible with existing algorithms.

QCoro::Generator<int> fibonacci() {
    quint64 a = 0, b = 0;
    Q_FOREVER {
        co_yield b;
        const auto tmp = b;
        a = b;
        b += tmp;
    }
}

void printFib(quint64 max) {
    for (auto fib : fibonacci()) {
        if (fib > max) {
            break;
        }
        std::cout << fib << std::endl;
    }
}

πŸ“˜ Full documentation here.

License

MIT License

Copyright (c) 2022 Daniel VrΓ‘til <[email protected]>

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.

qcoro's People

Contributors

a17r avatar alex-viking avatar captainurist avatar carlschwan avatar dangelog avatar danvratil avatar dependabot[bot] avatar developerpaul123 avatar dfaure avatar hannahkiekens avatar heirecka avatar ivknv avatar jbruechert avatar micahspikah avatar nicolasfella avatar nmariusp avatar r-value avatar rgriebl avatar shaan7 avatar sizeofvoid avatar vicr123 avatar xvitaly avatar ysc3839 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qcoro's Issues

Doesn't work on Debian 11?

Debian 11: gcc version 10.2.1
Build is fine after lowering cmake version requirement to 3.18 and removing include(HasCompatibleStlAbi) (doesn't work under 3.18 i think).

But in QtCreator in getting compile error on code:

const QDBusReply<UDisks2::Introspection> reply = co_await udisks2_iface.asyncCall(QStringLiteral("GetManagedObjects"));

error: unable to find the promise type for this coroutine

QtCreator doesn't like co_await keyword https://i.imgur.com/fUR5LRQ.png set(CMAKE_CXX_STANDARD 20) enabled

it possible to co_await forever on asyncCall?

I'm writing little usb-stick formatting utility using udisks2 via dbus. QCoro makes code insane simple, instead of chaining singals/slots with QDBusPendingCallWatcher using co_await on asyncCall. But on long operations QtDBus sends timeouts errors.

QCoro::Task<QDBusPendingReply<void>> UDisksHelper::createPartitionTable(const QString &devBlock)
{
    qDebug() << Q_FUNC_INFO;
    QDBusInterface block_iface(UDISKS2_SERVICE, devBlock, UDISKS2_BLOCK_INTERFACE, QDBusConnection::systemBus());
    QVariantMap options;
    options.insert("erase", "zero");
    const QDBusPendingReply<void> empty = co_await block_iface.asyncCall("Format", "empty", options);
    const QDBusPendingReply<void> reply = co_await block_iface.asyncCall("Format", "gpt", QVariantMap());
    co_return reply;
}
Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.", signature="s", contents=("Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

Fix QCoroNetwork linking for shared library

WaitSignalHelper defined in qcoroiodevice_p.h is used both in core and in network libraries. When using shared linking option, the build fails with log below. Using MSVC 19.29.30140.0 on Windows 10 and Qt 5.15.1.

[15/15] Linking CXX shared library bin\QCoro5Network.dll FAILED: bin/QCoro5Network.dll lib/QCoro5Network.lib cmd.exe /C "cmd.exe /C "E:\.conan\b280e9\1\bin\cmake.exe -E __create_def E:\.conan\ce448f\1\build_subfolder\source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\.\exports.def E:\.conan\ce448f\1\build_subfolder\source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\.\exports.def.objs && cd E:\.conan\ce448f\1\build_subfolder" && E:\.conan\b280e9\1\bin\cmake.exe -E vs_link_dll --intdir=source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100183~1.0\x64\mt.exe --manifests -- C:\PROGRA~2\MIB055~1\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\QCoro5Network_autogen\mocs_compilation.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcoroabstractsocket.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcorolocalsocket.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcoronetworkreply.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcorotcpserver.cpp.obj /out:bin\QCoro5Network.dll /implib:lib\QCoro5Network.lib /pdb:bin\QCoro5Network.pdb /dll /version:0.5 /machine:x64 /debug /INCREMENTAL /DEF:source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\.\exports.def lib\QCoro5Core.lib E:\.conan\4d51e9\1\lib\Qt5Network.lib E:\.conan\4d51e9\1\lib\Qt5Core.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." LINK Pass 1: command "C:\PROGRA~2\MIB055~1\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\link.exe /nologo source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\QCoro5Network_autogen\mocs_compilation.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcoroabstractsocket.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcorolocalsocket.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcoronetworkreply.cpp.obj source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\qcorotcpserver.cpp.obj /out:bin\QCoro5Network.dll /implib:lib\QCoro5Network.lib /pdb:bin\QCoro5Network.pdb /dll /version:0.5 /machine:x64 /debug /INCREMENTAL /DEF:source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir\.\exports.def lib\QCoro5Core.lib E:\.conan\4d51e9\1\lib\Qt5Network.lib E:\.conan\4d51e9\1\lib\Qt5Core.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir/intermediate.manifest source_subfolder\qcoro\network\CMakeFiles\QCoro5Network.dir/manifest.res" failed (exit code 1120) with the following output: Creating library lib\QCoro5Network.lib and object lib\QCoro5Network.exp qcoroabstractsocket.cpp.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const QCoro::detail::WaitSignalHelper::staticMetaObject" (?staticMetaObject@WaitSignalHelper@detail@QCoro@@2UQMetaObject@@B) qcorolocalsocket.cpp.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const QCoro::detail::WaitSignalHelper::staticMetaObject" (?staticMetaObject@WaitSignalHelper@detail@QCoro@@2UQMetaObject@@B) qcoronetworkreply.cpp.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const QCoro::detail::WaitSignalHelper::staticMetaObject" (?staticMetaObject@WaitSignalHelper@detail@QCoro@@2UQMetaObject@@B) bin\QCoro5Network.dll : fatal error LNK1120: 1 unresolved externals ninja: build stopped: subcommand failed.

Config-time Qt feature detection

Based on #44 it's clear we need to fix feature detection at config time.

  • Enable/disable QtDBus and QtNetwork support not purely based on platform IFs but rather by checking what features Qt is compiled with (because it's possible to have Qt on Linux without QtDBus, and QCoro should automatically detect it and not attempt to build QCoroDBus).
  • Expose information about which QCoro features are enabled in config.h
  • Check for QT_CONFIG(dbus) to adjust default QCORO_WITH_QTDBUS value
  • Check for QT_CONFIG(network) to adjust default QCORO_WITH_QTNETWORK value
  • Check for QT_CONFIG(process) to detect whether Qt is built with QProcess support (#44)
  • Check for QT_CONFIG(future) to detect whether Qt is built with QFuture support
  • Check for QT_CONFIG(localserver) to detect whether Qt is built with QLocalServer support (for QLocalSocket)
  • Check for QT_NO_EXCEPTION to detect whether Qt is built with exception support (#28)

Coroutine cancellation

It is desirable that coroutines can be cancelled from the outside. So far I came up with four possible solutions, each with their own set of advantages and drawbacks.

1. Using a stop token

Inside a coroutine, user would obtain a stop token (QCoro::thisCoroutine::stopToken()) for the current coroutine. The coroutine caller could cancel the coroutine through the Task<> object (calling task.cancel()).

βž• Gives the programmer more control over where to terminate the cancelled coroutine, allowing for additional cleanup of resources
βž– The programmer must manually check the stop token after each suspension point - failing so makes the coroutine "uncancellable"
βž– If a coroutine is cancelled because it would never be resumed (e.g. a coroutine awaiting a network message gets cancelled because the network is down, so the message will never arrive and the coroutine will never resume), the cancellation will have no real effect as the coroutine will remain suspended, never reaching the code that checks the stop token. I would consider this a memory leak.
βž– Non-void coroutine must return something, which may make the interface more complex.

QCoro::Task<> myCoro() {
    ...
    const auto result = co_await otherCoro();
    if (QCoro::thisCoroutine::stopToken().stop_requested()) {
        ...
        co_return;
    }
    ...
}

2. Using stop token and artificially resuming the cancelled coroutine

This works the same as the case above, but it tries to solve the last βž– by artificially resuming the suspended coroutine after it's been cancelled. This allows the coroutine to reach the code that checks the stop token and terminate.

βž• Coroutine termination is always guaranteed (unless the programmer makes a mistake and forgets to handle cancellation)
βž– If the cancelled coroutine is awaiting a result of another awaitable, artifically resuming it requires that we also provide some empty result (so all awaitables would have to have std::optional<T> or std::variant<T, QCoro::Cancelled> return type). This would make the API annoying to use, especially if T would be something like std::expect<U, E>, requiring the caller to first check T or Cancelled_t and if T then check U or E.
βž– Same as with the previous case, if the coroutine is non-void, it must return something.

QCoro::Task<> myCoro() {
    ...
    const auto result = co_await otherCoro();
    if (std::holds_alternative<QCoro::Cancelled>(result)) {
        ...
        co_return;
    }
    ...
}

3. Destroying the coroutine

When user cancels a coroutine, we could simply destroy the coroutine (std::coroutine_handle::destroy()) which takes care of destroying the coroutine's stack, including properly invoking destructors. The major danger of this approach is that it's easy to leak manually aquired resources if the resource lifetime crosses the suspension point.

βž• Always works
βž• Can be implemented completely inside Task<>
βž– Programmer loses control over the cancellation
βž– No chance for manual cleanup before terminating the coroutine can lead to memory leaks

❗Destroying the coroutine state does not automatically cascade to nested coroutines, and it may be tricky/impossible to implement. At best we would need to track currently awaited coroutines inside the cancelled coroutine's promise.

4. Throwing an exception from suspension point

When a suspended coroutine is canceled, it would be resumed, and await_resume() at the coroutine's suspension point would throw an exception (e.g. QCoro::CoroutineCanceled)

βž• Always works, as long as the awaitable that the coroutine is awaiting supports it
βž• If the programmer needs to handle cancellation in a special way, they can catch the exception, perform any cleanup, and then rethrow the exception to continue with cancelation.
βž• Can fallback to 3) if exceptions are disabled
βž– Requires support in custom awaitables
βž– Exceptions are non-standard pattern in the Qt ecosystem
βž– Requires exception support enabled

QCoro::Task<> myCoro() {
    ...
    try {
        const auto r = co_await otherCoro();
    } except (const QCoro::Cancelled &cancel) {
        ...
        throw cancel;
    }
    ...
}

I'm currently most in favor of 3, since it's the easiest to implement and has a minimal impact on user code. We could always scale up from there. I have yet to do some PoC implementation to verify whether it is workable.

`QSerialSocket` support

Discussed in #102

Originally posted by DeveloperPaul123 July 28, 2022
I noticed that some subclasses of QIODevice are supported such as QLocalSocket. Are there any plans to support QSerialSocket directly?

CI: GCC 12 support

Extend the matrix with GCC 12.

I couldn't find any PPA with gcc-12 for ubuntu 20.04 (used on the linux github runners), so we'll probably have to have a Docker image based on newer ubuntu with gcc 12 and necessary dev tools to build QCoro preinstalled.

Missing SOVERSION field

Installed shared libraries has no SOVERSION field:

-- Installing: /BUILDROOT/qcoro-0.2.0-1.fc34.x86_64/usr/lib64/libQCoroCore.so

Most of GNU/Linux distributions strictly requires it.

0.6.0 build fails because of -Werror

/build/qcoro/src/qcoro-0.6.0/qcoro/core/qcorosignal.h: In function β€˜operator()’:
/build/qcoro/src/qcoro-0.6.0/qcoro/core/qcorosignal.h:225:14: error: β€˜MEM[(struct QArrayDataPointer *)&result + 8B].d’ may be used uninitialized [-Werror=maybe-uninitialized]
  225 |         auto result = std::move(mQueue.front());
      |              ^
/build/qcoro/src/qcoro-0.6.0/qcoro/core/qcorosignal.h:225:14: error: β€˜MEM[(struct QArrayDataPointer *)&result + 8B].ptr’ may be used uninitialized [-Werror=maybe-uninitialized]

Please don't use -Werror in released code. Even if it works for you, it may break when using a different compiler or a different version of the same compiler, and it will surely break with future compiler versions, so you're artificially setting an expiration date on your code.

A slot called by qt, which is a coroutine: handling exceptions

Hi, I have this kind of code:

#include <iostream>
#include <QTimer>
#include <QCoreApplication>
#include <QCoroSignal>

struct Response {

};

class ServerConnection : public QObject {
    Q_OBJECT
public:
    ServerConnection()
    {
        // connect to the server...
        emit serverConnected();
    }
    Q_SIGNAL void serverConnected();

};

QCoro::Task<Response> sendMessage();

QCoro::Task<> onServerConnected()
{
    std::cerr << "doStuff()\n";
    // ... do stuff, maybe use sendMessage with co_await
    //
    // ...
    //
    throw std::runtime_error("Can't catch this");
}

int main(int argc, char* argv[])
{
    QCoreApplication app(argc, argv);
    auto srv_conn = new ServerConnection();
    QObject::connect(srv_conn, &ServerConnection::serverConnected, onServerConnected);
    app.exec();
}

I want to rework my current app to use qcoro. However, I don't want to rewrite all of the stuff at once. In the above code, I'd like to use coroutines inside the doStuff function. This means that doStuff itself must be a couroutine. My issue is that if doStuff throws, I have no way to handle that exception, because Qt doesn't call it with co_await (I'm not even sure how that would work!).

What do you think is the correct approach? Should I just wrap my "top-level" couroutine with a try-catch block and handle the exceptions there?

Is passing objects as reference from a coroutine to a coroutine function ok?

An example:

QCoro::Task<> MyClass::doSomethingWithData(QByteArray &data) {

...........................................

QNetworkAccessManager networkAccessManager;
const QNetworkReply *reply = co_await networkAccessManager.get(url);
...............................................

}

QCoro::Task<> MyClass::fetchData() {

QNetworkAccessManager networkAccessManager;
const QNetworkReply *reply = co_await networkAccessManager.get(url);
const auto data = reply->readAll();
doSomethingWithData(data)

}

Make exception support compile-time optional

Exceptions are not usually used with Qt and some project may choose to disable exception support (also it's possible to compile Qt without exception support), we should support that do and conditionally disable all exception-related code.

QMake configuration

There's demand for QMake support. I can either borrow the respective scripts from extra-cmake-modules or craft them manually, depending on how complex the config files are.

Investigate ASAN issues on Qt5 Windows build

The CI is failing due to ASAN issues on Qt5/Windows.

I currently have no means of debugging this issue locally, so ASAN is disabled on CI for Qt5 Windows for now, but I'd like to

  1. get better symbol names
  2. find out whether it is a real issue or a false positive
  3. either fix the problem in QCoro or create a supression rule

Details below:

test 12
      Start 12: test-qcoronetworkreply

12: Test command: D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-qcoronetworkreply.exe
12: Test timeout computed to be: 1500
12: warning: Environment variable QT_LOGGING_TO_CONSOLE is deprecated, use
12: QT_ASSUME_STDERR_HAS_CONSOLE and/or QT_FORCE_STDERR_LOGGING instead.
12: ********* Start testing of QCoroNetworkReplyTest *********
12: Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-llp64 shared (dynamic) release build; by MSVC 2019), windows server2016
12: PASS   : QCoroNetworkReplyTest::initTestCase()
12: =================================================================
12: ==5180==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x0229a2492cc0 in thread T2
12:     #0 0x7ff970beedb9  (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18004edb9)
12:     #1 0x7ff9a1cef4bd  (C:\Windows\System32\ucrtbase.dll+0x18000f4bd)
12:     #2 0x7ff9a1cef297  (C:\Windows\System32\ucrtbase.dll+0x18000f297)
12:     #3 0x7ff9a1cef13a  (C:\Windows\System32\ucrtbase.dll+0x18000f13a)
12:     #4 0x7ff9a1cef0e7  (C:\Windows\System32\ucrtbase.dll+0x18000f0e7)
12:     #5 0x7ff9719dc614  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1802dc614)
12:     #6 0x7ff9719dc630  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1802dc630)
12:     #7 0x7ff971855886  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180155886)
12:     #8 0x7ff971854266  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180154266)
12:     #9 0x7ff9717205a9  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1800205a9)
12:     #10 0x7ff97172051b  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x18002051b)
12:     #11 0x7ff971819c7b  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180119c7b)
12:     #12 0x7ff73a6e2c0d  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-qcoronetworkreply.exe+0x140002c0d)
12:     #13 0x7ff971725ee0  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180025ee0)
12:     #14 0x7ff970bfcb53  (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18005cb53)
12:     #15 0x7ff9a2dc4ecf  (C:\Windows\System32\KERNEL32.DLL+0x180014ecf)
12:     #16 0x7ff9a478e39a  (C:\Windows\SYSTEM32\ntdll.dll+0x18007e39a)
12: 
12: Address 0x0229a2492cc0 is a wild pointer.
12: SUMMARY: AddressSanitizer: bad-free (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18004edb9) 
12: Thread T2 created by T0 here:
12:     #0 0x7ff970bfd978  (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18005d978)
12:     #1 0x7ff971725c68  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180025c68)
12:     #2 0x7ff73a6e3aee  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-qcoronetworkreply.exe+0x140003aee)
12:     #3 0x7ff73a6e7928  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-qcoronetworkreply.exe+0x140007928)
12:     #4 0x7ff9718d892c  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1801d892c)
12:     #5 0x7ff98c4758de  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x1800058de)
12:     #6 0x7ff98c47554e  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x18000554e)
12:     #7 0x7ff98c47652d  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x18000652d)
12:     #8 0x7ff98c4799c4  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x1800099c4)
12:     #9 0x7ff98c4774f3  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x1800074f3)
12:     #10 0x7ff73a6ec530  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-qcoronetworkreply.exe+0x14000c530)
12:     #11 0x7ff73a6ffd0f  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-qcoronetworkreply.exe+0x14001fd0f)
12:     #12 0x7ff9a2dc4ecf  (C:\Windows\System32\KERNEL32.DLL+0x180014ecf)
12:     #13 0x7ff9a478e39a  (C:\Windows\SYSTEM32\ntdll.dll+0x18007e39a)
12: 
12: ==5180==ABORTING
12/14 Test #12: test-qcoronetworkreply ...........***Failed    2.28 sec
warning: Environment variable QT_LOGGING_TO_CONSOLE is deprecated, use
QT_ASSUME_STDERR_HAS_CONSOLE and/or QT_FORCE_STDERR_LOGGING instead.
test 14
      Start 14: test-testhttpserver

14: Test command: D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-testhttpserver.exe
14: Test timeout computed to be: 1500
14: warning: Environment variable QT_LOGGING_TO_CONSOLE is deprecated, use
14: QT_ASSUME_STDERR_HAS_CONSOLE and/or QT_FORCE_STDERR_LOGGING instead.
14: ********* Start testing of TestHttpServerTest *********
14: Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-llp64 shared (dynamic) release build; by MSVC 2019), windows server2016
14: PASS   : TestHttpServerTest::initTestCase()
14: =================================================================
14: ==6908==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x0221ec763a30 in thread T2
14:     #0 0x7ff970beedb9  (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18004edb9)
14:     #1 0x7ff9a1cef4bd  (C:\Windows\System32\ucrtbase.dll+0x18000f4bd)
14:     #2 0x7ff9a1cef297  (C:\Windows\System32\ucrtbase.dll+0x18000f297)
14:     #3 0x7ff9a1cef13a  (C:\Windows\System32\ucrtbase.dll+0x18000f13a)
14:     #4 0x7ff9a1cef0e7  (C:\Windows\System32\ucrtbase.dll+0x18000f0e7)
14:     #5 0x7ff9719dc614  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1802dc614)
14:     #6 0x7ff9719dc630  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1802dc630)
14:     #7 0x7ff971855886  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180155886)
14:     #8 0x7ff971854266  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180154266)
14:     #9 0x7ff9717205a9  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1800205a9)
14:     #10 0x7ff97172051b  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x18002051b)
14:     #11 0x7ff971819c7b  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180119c7b)
14:     #12 0x7ff759352a3d  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-testhttpserver.exe+0x140002a3d)
14:     #13 0x7ff971725ee0  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180025ee0)
14:     #14 0x7ff970bfcb53  (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18005cb53)
14:     #15 0x7ff9a2dc4ecf  (C:\Windows\System32\KERNEL32.DLL+0x180014ecf)
14:     #16 0x7ff9a478e39a  (C:\Windows\SYSTEM32\ntdll.dll+0x18007e39a)
14: 
14: Address 0x0221ec763a30 is a wild pointer.
14: SUMMARY: AddressSanitizer: bad-free (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18004edb9) 
14: Thread T2 created by T0 here:
14:     #0 0x7ff970bfd978  (C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\bin\HostX64\x64\clang_rt.asan_dynamic-x86_64.dll+0x18005d978)
14:     #1 0x7ff971725c68  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x180025c68)
14:     #2 0x7ff75935391e  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-testhttpserver.exe+0x14000391e)
14:     #3 0x7ff759355131  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-testhttpserver.exe+0x140005131)
14:     #4 0x7ff9718d892c  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Core.dll+0x1801d892c)
14:     #5 0x7ff98c4758de  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x1800058de)
14:     #6 0x7ff98c47554e  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x18000554e)
14:     #7 0x7ff98c47652d  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x18000652d)
14:     #8 0x7ff98c4799c4  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x1800099c4)
14:     #9 0x7ff98c4774f3  (C:\Qt\5.15.2\msvc2019_64\bin\Qt5Test.dll+0x1800074f3)
14:     #10 0x7ff7593560d0  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-testhttpserver.exe+0x1400060d0)
14:     #11 0x7ff759356eaf  (D:\a\qcoro\qcoro\build\tests\RelWithDebInfo\test-testhttpserver.exe+0x140006eaf)
14:     #12 0x7ff9a2dc4ecf  (C:\Windows\System32\KERNEL32.DLL+0x180014ecf)
14:     #13 0x7ff9a478e39a  (C:\Windows\SYSTEM32\ntdll.dll+0x18007e39a)
14: 
14: ==6908==ABORTING
14/14 Test #14: test-testhttpserver ..............***Failed    0.55 sec

qcoro fails to build with gcc 11.3.0 and 12.0.1_pre20220424

...
[ 20%] οΏ½[32mοΏ½[1mLinking CXX executable await-sync-stringοΏ½[0m
cd /var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build/examples/basics && /usr/x86_64-pc-linux-gnu/bin/cmake -E cmake_link_script CMakeFiles/await-sync-string.dir/link.txt --verbose=1
/usr/bin/x86_64-pc-linux-gnu-c++ -march=native -O2 -pipe -Wall -Wextra -Werror -pedantic -fcoroutines -Wl,-O1 -Wl,--as-needed "CMakeFiles/await-sync-string.dir/await-sync-string_autogen/mocs_compilation.cpp.o" "CMakeFiles/await-sync-string.dir/await-sync-string.cpp.o" -o await-sync-string 
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
[ 20%] Built target await-sync-string
In file included from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.cpp:6οΏ½[mοΏ½[K:
/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h: In instantiation of 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type> qCoro(T*, FuncPtr&&, std::chrono::milliseconds) [with T = const QProcess; FuncPtr = void (QProcess::*)(QProcess::QPrivateSignal); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<QProcess::QPrivateSignal>; std::chrono::milliseconds = std::chrono::duration<long int, std::ratio<1, 1000> >]οΏ½[mοΏ½[K':
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.cpp:23:44:οΏ½[mοΏ½[K   required from here
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:131:19:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(QProcess::QPrivateSignal)>::QCoroSignal(const QCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(QProcess::QPrivateSignal)>&)οΏ½[mοΏ½[K'
  131 |     auto result = οΏ½[01;31mοΏ½[Kco_awaitοΏ½[mοΏ½[K coroSignal;
      |                   οΏ½[01;31mοΏ½[K^~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[K'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(QProcess::QPrivateSignal)>::QCoroSignal(const QCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(QProcess::QPrivateSignal)>&)οΏ½[mοΏ½[K' is implicitly deleted because the default definition would be ill-formed:
   56 | class οΏ½[01;36mοΏ½[KQCoroSignalοΏ½[mοΏ½[K {
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[Kstd::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = QTimer; _Dp = std::default_delete<QTimer>]οΏ½[mοΏ½[K'
In file included from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/memory:76οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/waitoperationbase_p.h:11οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.h:7οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.cpp:5οΏ½[mοΏ½[K:
οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/bits/unique_ptr.h:468:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[Kdeclared here
  468 |       οΏ½[01;36mοΏ½[Kunique_ptrοΏ½[mοΏ½[K(const unique_ptr&) = delete;
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~οΏ½[mοΏ½[K
In file included from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.cpp:6οΏ½[mοΏ½[K:
/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h: In instantiation of 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type> qCoro(T*, FuncPtr&&, std::chrono::milliseconds) [with T = const QProcess; FuncPtr = void (QProcess::*)(int, QProcess::ExitStatus); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<std::tuple<int, QProcess::ExitStatus> >; std::chrono::milliseconds = std::chrono::duration<long int, std::ratio<1, 1000> >]οΏ½[mοΏ½[K':
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.cpp:40:41:οΏ½[mοΏ½[K   required from here
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:131:19:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(int, QProcess::ExitStatus)>::QCoroSignal(const QCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(int, QProcess::ExitStatus)>&)οΏ½[mοΏ½[K'
  131 |     auto result = οΏ½[01;31mοΏ½[Kco_awaitοΏ½[mοΏ½[K coroSignal;
      |                   οΏ½[01;31mοΏ½[K^~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[K'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(int, QProcess::ExitStatus)>::QCoroSignal(const QCoro::detail::QCoroSignal<const QProcess, void (QProcess::*)(int, QProcess::ExitStatus)>&)οΏ½[mοΏ½[K' is implicitly deleted because the default definition would be ill-formed:
   56 | class οΏ½[01;36mοΏ½[KQCoroSignalοΏ½[mοΏ½[K {
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[Kstd::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = QTimer; _Dp = std::default_delete<QTimer>]οΏ½[mοΏ½[K'
In file included from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/memory:76οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/waitoperationbase_p.h:11οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.h:7οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroprocess.cpp:5οΏ½[mοΏ½[K:
οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/bits/unique_ptr.h:468:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[Kdeclared here
  468 |       οΏ½[01;36mοΏ½[Kunique_ptrοΏ½[mοΏ½[K(const unique_ptr&) = delete;
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~οΏ½[mοΏ½[K
In file included from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.cpp:7οΏ½[mοΏ½[K:
/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h: In instantiation of 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type> qCoro(T*, FuncPtr&&, std::chrono::milliseconds) [with T = QCoro::detail::WaitSignalHelper; FuncPtr = void (QCoro::detail::WaitSignalHelper::*)(bool); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<bool>; std::chrono::milliseconds = std::chrono::duration<long int, std::ratio<1, 1000> >]οΏ½[mοΏ½[K':
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.cpp:128:29:οΏ½[mοΏ½[K   required from here
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:131:19:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(bool)>::QCoroSignal(const QCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(bool)>&)οΏ½[mοΏ½[K'
  131 |     auto result = οΏ½[01;31mοΏ½[Kco_awaitοΏ½[mοΏ½[K coroSignal;
      |                   οΏ½[01;31mοΏ½[K^~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[K'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(bool)>::QCoroSignal(const QCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(bool)>&)οΏ½[mοΏ½[K' is implicitly deleted because the default definition would be ill-formed:
   56 | class οΏ½[01;36mοΏ½[KQCoroSignalοΏ½[mοΏ½[K {
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[Kstd::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = QTimer; _Dp = std::default_delete<QTimer>]οΏ½[mοΏ½[K'
In file included from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/memory:76οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/task.h:12οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.h:7οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.cpp:5οΏ½[mοΏ½[K:
οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/bits/unique_ptr.h:468:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[Kdeclared here
  468 |       οΏ½[01;36mοΏ½[Kunique_ptrοΏ½[mοΏ½[K(const unique_ptr&) = delete;
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~οΏ½[mοΏ½[K
In file included from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.cpp:7οΏ½[mοΏ½[K:
/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h: In instantiation of 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type> qCoro(T*, FuncPtr&&, std::chrono::milliseconds) [with T = QCoro::detail::WaitSignalHelper; FuncPtr = void (QCoro::detail::WaitSignalHelper::*)(long long int); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<long long int>; std::chrono::milliseconds = std::chrono::duration<long int, std::ratio<1, 1000> >]οΏ½[mοΏ½[K':
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.cpp:133:29:οΏ½[mοΏ½[K   required from here
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:131:19:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(long long int)>::QCoroSignal(const QCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(long long int)>&)οΏ½[mοΏ½[K'
  131 |     auto result = οΏ½[01;31mοΏ½[Kco_awaitοΏ½[mοΏ½[K coroSignal;
      |                   οΏ½[01;31mοΏ½[K^~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[K'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(long long int)>::QCoroSignal(const QCoro::detail::QCoroSignal<QCoro::detail::WaitSignalHelper, void (QCoro::detail::WaitSignalHelper::*)(long long int)>&)οΏ½[mοΏ½[K' is implicitly deleted because the default definition would be ill-formed:
   56 | class οΏ½[01;36mοΏ½[KQCoroSignalοΏ½[mοΏ½[K {
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[Kstd::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = QTimer; _Dp = std::default_delete<QTimer>]οΏ½[mοΏ½[K'
In file included from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/memory:76οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/task.h:12οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.h:7οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcoroiodevice.cpp:5οΏ½[mοΏ½[K:
οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/bits/unique_ptr.h:468:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[Kdeclared here
  468 |       οΏ½[01;36mοΏ½[Kunique_ptrοΏ½[mοΏ½[K(const unique_ptr&) = delete;
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~οΏ½[mοΏ½[K
make[2]: *** [qcoro/core/CMakeFiles/QCoro5Core.dir/build.make:121: qcoro/core/CMakeFiles/QCoro5Core.dir/qcoroprocess.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: *** [qcoro/core/CMakeFiles/QCoro5Core.dir/build.make:93: qcoro/core/CMakeFiles/QCoro5Core.dir/qcoroiodevice.cpp.o] Error 1
In file included from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorothread.cpp:6οΏ½[mοΏ½[K:
/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h: In instantiation of 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type> qCoro(T*, FuncPtr&&, std::chrono::milliseconds) [with T = QThread; FuncPtr = void (QThread::*)(QThread::QPrivateSignal); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<QThread::QPrivateSignal>; std::chrono::milliseconds = std::chrono::duration<long int, std::ratio<1, 1000> >]οΏ½[mοΏ½[K':
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorothread.cpp:24:39:οΏ½[mοΏ½[K   required from here
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:131:19:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QThread, void (QThread::*)(QThread::QPrivateSignal)>::QCoroSignal(const QCoro::detail::QCoroSignal<QThread, void (QThread::*)(QThread::QPrivateSignal)>&)οΏ½[mοΏ½[K'
  131 |     auto result = οΏ½[01;31mοΏ½[Kco_awaitοΏ½[mοΏ½[K coroSignal;
      |                   οΏ½[01;31mοΏ½[K^~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[K'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QThread, void (QThread::*)(QThread::QPrivateSignal)>::QCoroSignal(const QCoro::detail::QCoroSignal<QThread, void (QThread::*)(QThread::QPrivateSignal)>&)οΏ½[mοΏ½[K' is implicitly deleted because the default definition would be ill-formed:
   56 | class οΏ½[01;36mοΏ½[KQCoroSignalοΏ½[mοΏ½[K {
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[Kstd::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = QTimer; _Dp = std::default_delete<QTimer>]οΏ½[mοΏ½[K'
In file included from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/memory:76οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/qt5/QtCore/qsharedpointer_impl.h:71οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/qt5/QtCore/qsharedpointer.h:48οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/qt5/QtCore/qpointer.h:43οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/qt5/QtCore/QPointer:1οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorothread.h:7οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorothread.cpp:5οΏ½[mοΏ½[K:
οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/bits/unique_ptr.h:468:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[Kdeclared here
  468 |       οΏ½[01;36mοΏ½[Kunique_ptrοΏ½[mοΏ½[K(const unique_ptr&) = delete;
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~οΏ½[mοΏ½[K
In file included from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorotimer.cpp:6οΏ½[mοΏ½[K:
/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h: In instantiation of 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type> qCoro(T*, FuncPtr&&, std::chrono::milliseconds) [with T = QTimer; FuncPtr = void (QTimer::*)(QTimer::QPrivateSignal); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<QTimer::QPrivateSignal>; std::chrono::milliseconds = std::chrono::duration<long int, std::ratio<1, 1000> >]οΏ½[mοΏ½[K':
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:149:45:οΏ½[mοΏ½[K   required from 'οΏ½[01mοΏ½[KQCoro::Task<typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type::value_type> qCoro(T*, FuncPtr&&) [with T = QTimer; FuncPtr = void (QTimer::*)(QTimer::QPrivateSignal); typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type::value_type = QTimer::QPrivateSignal; typename QCoro::detail::QCoroSignal<T, FuncPtr>::result_type = std::optional<QTimer::QPrivateSignal>]οΏ½[mοΏ½[K'
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorotimer.cpp:41:23:οΏ½[mοΏ½[K   required from here
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:131:19:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QTimer, void (QTimer::*)(QTimer::QPrivateSignal)>::QCoroSignal(const QCoro::detail::QCoroSignal<QTimer, void (QTimer::*)(QTimer::QPrivateSignal)>&)οΏ½[mοΏ½[K'
  131 |     auto result = οΏ½[01;31mοΏ½[Kco_awaitοΏ½[mοΏ½[K coroSignal;
      |                   οΏ½[01;31mοΏ½[K^~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[K'οΏ½[01mοΏ½[KQCoro::detail::QCoroSignal<QTimer, void (QTimer::*)(QTimer::QPrivateSignal)>::QCoroSignal(const QCoro::detail::QCoroSignal<QTimer, void (QTimer::*)(QTimer::QPrivateSignal)>&)οΏ½[mοΏ½[K' is implicitly deleted because the default definition would be ill-formed:
   56 | class οΏ½[01;36mοΏ½[KQCoroSignalοΏ½[mοΏ½[K {
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~~οΏ½[mοΏ½[K
οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorosignal.h:56:7:οΏ½[mοΏ½[K οΏ½[01;31mοΏ½[Kerror: οΏ½[mοΏ½[Kuse of deleted function 'οΏ½[01mοΏ½[Kstd::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = QTimer; _Dp = std::default_delete<QTimer>]οΏ½[mοΏ½[K'
In file included from οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/memory:76οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/task.h:12οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorotimer.h:7οΏ½[mοΏ½[K,
                 from οΏ½[01mοΏ½[K/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qcoro-0.5.0/qcoro/core/qcorotimer.cpp:5οΏ½[mοΏ½[K:
οΏ½[01mοΏ½[K/usr/x86_64-pc-linux-gnu/include/c++/11.3.0/bits/unique_ptr.h:468:7:οΏ½[mοΏ½[K οΏ½[01;36mοΏ½[Knote: οΏ½[mοΏ½[Kdeclared here
  468 |       οΏ½[01;36mοΏ½[Kunique_ptrοΏ½[mοΏ½[K(const unique_ptr&) = delete;
      |       οΏ½[01;36mοΏ½[K^~~~~~~~~~οΏ½[mοΏ½[K
[ 21%] οΏ½[32mοΏ½[1mLinking CXX executable testdbusserverοΏ½[0m
cd /var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build/tests && /usr/x86_64-pc-linux-gnu/bin/cmake -E cmake_link_script CMakeFiles/testdbusserver.dir/link.txt --verbose=1
/usr/bin/x86_64-pc-linux-gnu-c++ -march=native -O2 -pipe -Wall -Wextra -Werror -pedantic -fcoroutines -Wl,-O1 -Wl,--as-needed CMakeFiles/testdbusserver.dir/testdbusserver_autogen/mocs_compilation.cpp.o CMakeFiles/testdbusserver.dir/testdbusserver.cpp.o -o testdbusserver  /usr/x86_64-pc-linux-gnu/lib/libQt5DBus.so.5.15.3 /usr/x86_64-pc-linux-gnu/lib/libQt5Core.so.5.15.3 
[ 22%] οΏ½[32mοΏ½[1mLinking CXX executable await-async-stringοΏ½[0m
cd /var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build/examples/basics && /usr/x86_64-pc-linux-gnu/bin/cmake -E cmake_link_script CMakeFiles/await-async-string.dir/link.txt --verbose=1
/usr/bin/x86_64-pc-linux-gnu-c++ -march=native -O2 -pipe -Wall -Wextra -Werror -pedantic -fcoroutines -Wl,-O1 -Wl,--as-needed "CMakeFiles/await-async-string.dir/await-async-string_autogen/mocs_compilation.cpp.o" "CMakeFiles/await-async-string.dir/await-async-string.cpp.o" -o await-async-string  /usr/x86_64-pc-linux-gnu/lib/libQt5Core.so.5.15.3 
make[2]: *** [qcoro/core/CMakeFiles/QCoro5Core.dir/build.make:149: qcoro/core/CMakeFiles/QCoro5Core.dir/qcorotimer.cpp.o] Error 1
[ 23%] οΏ½[32mοΏ½[1mLinking CXX executable dbusserverοΏ½[0m
cd /var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build/examples/dbus/common && /usr/x86_64-pc-linux-gnu/bin/cmake -E cmake_link_script CMakeFiles/dbusserver.dir/link.txt --verbose=1
/usr/bin/x86_64-pc-linux-gnu-c++ -march=native -O2 -pipe -Wall -Wextra -Werror -pedantic -fcoroutines -Wl,-O1 -Wl,--as-needed CMakeFiles/dbusserver.dir/dbusserver_autogen/mocs_compilation.cpp.o CMakeFiles/dbusserver.dir/dbusserver.cpp.o -o dbusserver  /usr/x86_64-pc-linux-gnu/lib/libQt5DBus.so.5.15.3 /usr/x86_64-pc-linux-gnu/lib/libQt5Core.so.5.15.3 
make[2]: *** [qcoro/core/CMakeFiles/QCoro5Core.dir/build.make:135: qcoro/core/CMakeFiles/QCoro5Core.dir/qcorothread.cpp.o] Error 1
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
make[1]: *** [CMakeFiles/Makefile2:1165: qcoro/core/CMakeFiles/QCoro5Core.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
[ 24%] οΏ½[32mοΏ½[1mLinking CXX static library libexamples-dbus-common.aοΏ½[0m
cd /var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build/examples/dbus/common && /usr/x86_64-pc-linux-gnu/bin/cmake -P CMakeFiles/examples-dbus-common.dir/cmake_clean_target.cmake
cd /var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build/examples/dbus/common && /usr/x86_64-pc-linux-gnu/bin/cmake -E cmake_link_script CMakeFiles/examples-dbus-common.dir/link.txt --verbose=1
x86_64-pc-linux-gnu-ar qc libexamples-dbus-common.a "CMakeFiles/examples-dbus-common.dir/examples-dbus-common_autogen/mocs_compilation.cpp.o" "CMakeFiles/examples-dbus-common.dir/dbusserver.cpp.o"
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
x86_64-pc-linux-gnu-ranlib libexamples-dbus-common.a
[ 24%] Built target testdbusserver
[ 24%] Built target await-async-string
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
[ 24%] Built target examples-dbus-common
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
[ 24%] Built target dbusserver
make[2]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
[ 24%] Built target qcoro_test_dbus
make[1]: Leaving directory '/var/tmp/paludis/build/dev-libs-qcoro-0.5.0/work/qt5-build'
make: *** [Makefile:149: all] Error 2

Not sure if that's a problem of gcc or qcoro, but it works with gcc 10.3.0 and clang 13.0.1.

Rename task.h to qcorotask.h

All headers in QCoro have QCoro prefix, except for Task. There can be different libraries (private or public) which also use this term. It would be more readable and less conflicting to rename it to QCoroTask.

Additionally QCoroTaskFwd could be introduced to reduce code duplication when forward declaring coroutines in headers:

namespace QCoro {
template<typename T>
class Task;
}

Investigate websocket test timeouts on Windows CI

I've been seeing those a lot recently, the websockets test fail due to the coroutine timing out. This could point to an actual bug in the WebSockets implementation (at least on Windows) where we are missing some signal. Or it's simply a timeout issue like many we've seen before with the CI... :)

Qt5 and Qt6 versions use the same filename and soname

Qt 5 and Qt 6 versions of QCoro use the same filename and soname, so they can't coexist on the same system without using rpath tricks and/or LD_LIBRARY_PATH/LD_PRELOAD and friends.
It may make sense to use a naming scheme similar to Qt's own libraries (--> libQt5Coro.so.* / libQt6Coro.so.*)

Awaiting with context object.

In some cases, one might want to update an object (for example a model), when a coroutine finished.
This can be done by either using a lambda that captures this as a coroutine, or by adding a coroutine member function.
However there is no guarantee that once the coroutine finishes, the object still exists, so this can lead to crashes.

It is pretty much the same issue as the 3-arg connect in Qt: https://github.com/KDE/clazy/blob/master/docs/checks/README-connect-3arg-lambda.md

Is this already a solved problem in some way that I have missed?

If not, I propose adding an overload of QCoro::Task<T>::then that takes a QObject pointer as an additional argument, so that it can connect to QObject::destroyed of the context object, and not invoke the continuation if the signal has been emitted in the meantime.

I currently can't find a good way to fix this when using the co_await keyword, but as this mostly concerns the issue of interaction between coroutine code and sync code, support in .then is probably enough.

If needed, there could be something like

co_await someFunctionReturningTask().withContext(this)

to inject the context even though using co_await.

I already have code for some of the proposed things here, so I can work on implementing it if needed.

qcorotcpserver ASAN error with clang 15

Some time during May something has changed in clang that causes qcorotcpservertest to fail under ASAN.

  • Investigate what change to compiler has triggered this
  • Investigate whether it is a real bug in our code, or miscompilation

clang-cl doesn't recoganise command line option "-fcoroutines-ts"

As titled. But it works like MSVC, leaving blank is OK. Maybe something like below:

macro(qcoro_enable_coroutines)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines")
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts")
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        if (MSVC)
            # Clang-cl works like MSVC that auto-enables coroutine support when C++20 is enabled
        else()
            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts")
        endif()
    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
        # MSVC auto-enables coroutine support when C++20 is enabled
    else()
        message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER_ID} is not currently supported.")
    endif()
endmacro()

A class with `operator co_await()` should be treated as `Awaitable`

According to https://en.cppreference.com/w/cpp/language/coroutines#co_await:
if overload resolution for operator co_await gives a single best overload, the awaiter is the result of that call (awaitable.operator co_await() for member overload, operator co_await(static_cast<Awaitable&&>(awaitable)) for the non-member overload)

qcoro/qcoro/coroutine.h

Lines 23 to 33 in 353aacf

//! A concept describing the Awaitable type
/*!
* Awaitable type is a type that can be passed as an argument to co_await.
*/
template<typename T>
concept Awaitable = requires(T t) {
{ t.await_ready() }
->std::same_as<bool>;
{t.await_suspend(std::declval<QCORO_STD::coroutine_handle<>>())};
{t.await_resume()};
};
Currently co_await a class with operator co_await() cause an error.

Broken examples in docs

apple-clang support

Hello, I'm currently trying to make a conan package for qcoro on conan-io/conan-center-index#8870,
but the build on apple-clang 12 fails with

/Users/jenkins/w/BuildSingleReference@3/.conan/data/qcoro/0.4.0/_/_/build/77eb698670f46be85ef6b72390c811f44c09c9aa/source_subfolder/qcoro/concepts_p.h:9:10: fatal error: 'concepts' file not found
#include <concepts>

More details on https://c3i.jfrog.io/c3i/misc/logs/pr/8870/5-configs/macos-clang/qcoro/0.4.0//77eb698670f46be85ef6b72390c811f44c09c9aa-build.txt

is apple-clang supported ? If yes, starting with which version ?

Thanks !

CI: Re-enable ASAN in clang-cl builds

I was able to get qcoro compiled with ASAN using clang-cl, but the executables seem broken - they don't start - I suspect it could be the mix of Qt libs and clang's asan (??), but I have no clue, really...

Some tests failed on 0.4.0 due to low timeout

Sometimes qcoroabstractsocket test fails (50/50) on 0.4.0:

+ /usr/bin/ctest --output-on-failure --force-new-ctest-process -j4 --exclude-regex test-qcoroprocess
Test project /builddir/build/BUILD/qcoro-0.4.0/release-qt5/redhat-linux-build
      Start  1: test-qtimer
      Start  2: test-qcorosignal
      Start  3: test-task
      Start  4: test-testconstraints
 1/12 Test  #4: test-testconstraints .............   Passed    0.01 sec
      Start  5: test-qfuture
 2/12 Test  #2: test-qcorosignal .................   Passed    0.31 sec
      Start  6: test-qdbuspendingcall
 3/12 Test  #1: test-qtimer ......................   Passed    0.72 sec
      Start  7: test-qdbuspendingreply
 4/12 Test  #5: test-qfuture .....................   Passed    0.91 sec
      Start  8: test-qcorolocalsocket
 5/12 Test  #6: test-qdbuspendingcall ............   Passed    1.12 sec
      Start  9: test-qcoroabstractsocket
 6/12 Test  #3: test-task ........................   Passed    1.88 sec
      Start 10: test-qcoronetworkreply
 7/12 Test  #7: test-qdbuspendingreply ...........   Passed    3.12 sec
      Start 11: test-qcorotcpserver
 8/12 Test #11: test-qcorotcpserver ..............   Passed    0.51 sec
      Start 12: test-testhttpserver
 9/12 Test #12: test-testhttpserver ..............   Passed    1.52 sec
10/12 Test  #8: test-qcorolocalsocket ............   Passed    5.05 sec
11/12 Test #10: test-qcoronetworkreply ...........   Passed    4.52 sec
12/12 Test  #9: test-qcoroabstractsocket .........***Failed    5.05 sec
********* Start testing of QCoroAbstractSocketTest *********
Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 11.2.1 20210728 (Red Hat 11.2.1-1)), fedora 35
PASS   : QCoroAbstractSocketTest::initTestCase()
PASS   : QCoroAbstractSocketTest::testWaitForConnectedTriggers()
PASS   : QCoroAbstractSocketTest::testWaitForConnectedTimeout()
PASS   : QCoroAbstractSocketTest::testWaitForDisconnectedTriggers()
PASS   : QCoroAbstractSocketTest::testWaitForDisconnectedTimeout()
FAIL!  : QCoroAbstractSocketTest::testDoesntCoAwaitConnectedSocket() No incoming connection within timeout!
   Loc: [/builddir/build/BUILD/qcoro-0.4.0/tests/testhttpserver.h(99)]
PASS   : QCoroAbstractSocketTest::testDoesntCoAwaitDisconnectedSocket()
PASS   : QCoroAbstractSocketTest::testConnectToServerWithArgs()
PASS   : QCoroAbstractSocketTest::testReadAllTriggers()
PASS   : QCoroAbstractSocketTest::testReadTriggers()
PASS   : QCoroAbstractSocketTest::testReadLineTriggers()
PASS   : QCoroAbstractSocketTest::cleanupTestCase()
Totals: 11 passed, 1 failed, 0 skipped, 0 blacklisted, 5041ms
********* Finished testing of QCoroAbstractSocketTest *********


92% tests passed, 1 tests failed out of 12

Total Test time (real) =   6.48 sec

The following tests FAILED:
          9 - test-qcoroabstractsocket (Failed)
Errors while running CTest

Cannot await QDBusPendingReply with multiple parameters

This code fails to build

QDBusPendingReply<QString, int> reply;
co_await reply;

with

/home/nico/kde/src/plasma-nm/libs/handler.cpp:661:14: error: no matching function for call to 'QCoro::detail::TaskPromise<void>::await_transform(QDBusPendingReply<QString, int>&)'
  661 |     co_await reply;
      |              ^~~~~
In file included from /home/nico/kde/src/plasma-nm/libs/handler.h:21,
                 from /home/nico/kde/src/plasma-nm/libs/handler.cpp:7:
/home/nico/kde/usr/include/qcoro/task.h:164:10: note: candidate: 'template<class T, class Awaiter> auto QCoro::detail::TaskPromiseBase::await_transform(T&&)'
  164 |     auto await_transform(T &&value) {
      |          ^~~~~~~~~~~~~~~
/home/nico/kde/usr/include/qcoro/task.h:164:10: note:   template argument deduction/substitution failed:
/home/nico/kde/usr/include/qcoro/task.h: In substitution of 'template<class T> using awaiter_type_t = typename QCoro::detail::awaiter_type<T>::type [with T = QDBusPendingReply<QString, int>]':
/home/nico/kde/usr/include/qcoro/task.h:163:26:   required from here
/home/nico/kde/usr/include/qcoro/task.h:32:7: error: invalid use of incomplete type 'struct QCoro::detail::awaiter_type<QDBusPendingReply<QString, int>, void>'
   32 | using awaiter_type_t = typename awaiter_type<T>::type;
      |       ^~~~~~~~~~~~~~
/home/nico/kde/usr/include/qcoro/task.h:29:8: note: declaration of 'struct QCoro::detail::awaiter_type<QDBusPendingReply<QString, int>, void>'
   29 | struct awaiter_type;
      |        ^~~~~~~~~~~~
/home/nico/kde/usr/include/qcoro/task.h:190:10: note: candidate: 'template<class T> auto QCoro::detail::TaskPromiseBase::await_transform(QCoro::Task<T>&&)'
  190 |     auto await_transform(QCoro::Task<T> &&task) {
      |          ^~~~~~~~~~~~~~~
/home/nico/kde/usr/include/qcoro/task.h:190:10: note:   template argument deduction/substitution failed:
/home/nico/kde/src/plasma-nm/libs/handler.cpp:661:14: note:   'QDBusPendingReply<QString, int>' is not derived from 'QCoro::Task<T>'
  661 |     co_await reply;
      |              ^~~~~
In file included from /home/nico/kde/src/plasma-nm/libs/handler.h:21,
                 from /home/nico/kde/src/plasma-nm/libs/handler.cpp:7:
/home/nico/kde/usr/include/qcoro/task.h:196:11: note: candidate: 'template<class T> auto& QCoro::detail::TaskPromiseBase::await_transform(QCoro::Task<T>&)'
  196 |     auto &await_transform(QCoro::Task<T> &task) {
      |           ^~~~~~~~~~~~~~~
/home/nico/kde/usr/include/qcoro/task.h:196:11: note:   template argument deduction/substitution failed:
/home/nico/kde/src/plasma-nm/libs/handler.cpp:661:14: note:   'QDBusPendingReply<QString, int>' is not derived from 'QCoro::Task<T>'
  661 |     co_await reply;
      |              ^~~~~
In file included from /home/nico/kde/src/plasma-nm/libs/handler.h:21,
                 from /home/nico/kde/src/plasma-nm/libs/handler.cpp:7:
/home/nico/kde/usr/include/qcoro/task.h:202:10: note: candidate: 'template<class T>  requires  Awaitable<T> auto QCoro::detail::TaskPromiseBase::await_transform(T&&)'
  202 |     auto await_transform(T &&awaitable) {
      |          ^~~~~~~~~~~~~~~
/home/nico/kde/usr/include/qcoro/task.h:202:10: note:   template argument deduction/substitution failed:
/home/nico/kde/usr/include/qcoro/task.h:202:10: note: constraints not satisfied
In file included from /home/nico/kde/usr/include/qcoro/task.h:7,
                 from /home/nico/kde/src/plasma-nm/libs/handler.h:21,
                 from /home/nico/kde/src/plasma-nm/libs/handler.cpp:7:
/home/nico/kde/src/plasma-nm/libs/handler.cpp: In substitution of 'template<class T>  requires  Awaitable<T> auto QCoro::detail::TaskPromiseBase::await_transform(T&&) [with T = QDBusPendingReply<QString, int>&]':
/home/nico/kde/src/plasma-nm/libs/handler.cpp:661:14:   required from here
/home/nico/kde/usr/include/qcoro/coroutine.h:46:9:   required for the satisfaction of 'Awaitable<T>' [with T = QDBusPendingReply<QString, int, void, void, void, void, void, void>&]
/home/nico/kde/usr/include/qcoro/coroutine.h:46:53: note: no operand of the disjunction is satisfied
   46 | concept Awaitable = detail::has_operator_coawait<T> ||
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
   47 |                     detail::has_await_methods<T>;
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~     

Distinguish between clang and libc++ in macros

Currently we use #ifdef __clang__ to conditionally toggle code, even if the real reason for the toggle is libc++, rather than clang. We should throughly review all the ifdefs and see where the ifdef really should be about libc++ version rather than clang itself.

Documentation issue

On the documentation site, the "Continue Reading" links of QCoro 0.6.0 Release Announcement and others, jump to nothing.
(https://qcoro.dvratil.cz/news/#blog-p1)

Also, the way the QCoro 0.6 introduction is written is misleading in the sense one could think "apple-clang support" is deprecated, while I think you mean the opposite.

co_awaiting multiple tasks in parallel

I have already ran into a case in QCoro where being able to co_await multiple tasks in parallel would make the code simpler , and I think there's a lot of potential hidden in this feature.

The idea of for the API is:

// co_await two tasks, return result of both as a tuple
template<typename T1, typename T2>
Task<std::tuple<T1, T2>> operator && (Task<T1>, Task<T2>);
// co_await two tasks, return result of the first task to finish, cancel the other
template<typename T1, typename T2>
Task<std::variant<T1, T2>> operator || (Task<T1>, Task<T2>);

There's a question of composability, .e.g. should

co_await task1 && task2 && task3;

return std::tuple<T1, T2, T3> or std::tuple<std::tuple<T1, T2>, T3>?

Same goes for the operator|| - should the result be std::variant<T1, T2, T3> or std::variant<std::variant<T1, T2>, T3>?

I see benefit in having both, so I guess we could have allOf and firstOf functions to provide the flat result (as shown below) and leave the operator|| and operator&& to return the nested types following the natural rules of operator precedence.

template<typename Ts ...> Task<std::tuple<Ts ...>> allOf(Task<Ts> ...);
template<typename Ts ...> Task<std::variant<Ts ...>> firstOf(Task<Ts> ...);

Early co_returns do not resume the caller

Maybe I'm not understanding correctly how coroutines work, but I think the following example should work for both cases: returning early and awaited from testReturn.
What I'm seeing (gcc 11 and MSVC 2019) is that testImmediate just hangs and never returns from its co_await

static QCoro::Task<bool> testReturn(bool immediate)
{
    qWarning() << "Running testReturn(immediate:" << immediate << ")";
    if (immediate) {
        co_return true;
    } else {
        QTimer t;
        t.start(100);
        co_await(t);
        co_return true;
    }
}

static QCoro::Task<> testImmediate()
{
    qWarning() << "Starting Immediate...";
    bool b = co_await testReturn(true);
    qWarning() << "Immediate result:" << b;
}

static QCoro::Task<> testDelayed()
{
    qWarning() << "Starting Delayed...";
    bool b = co_await testReturn(false);
    qWarning() << "Delayed result:" << b;
}

int main(int argc, char **argv)
{
    QCoreApplication a(argc, argv);
    QMetaObject::invokeMethod(qApp, []{ testImmediate(); }, Qt::QueuedConnection);
    QMetaObject::invokeMethod(qApp, []{ testDelayed(); }, Qt::QueuedConnection);
    return a.exec();
}

Output:

Starting Immediate...
Running testReturn(immediate: true )
Starting Delayed...
Running testReturn(immediate: false )
Delayed result: true

Default compiler flags cause build issues on ARM

CMake isn't smart enough to actually print the error even when tracing, but here's what happens with 0.4:

qcore sets '-Wall -Wextra -Werror -pedantic' before looking for Qt.

QtWidgets β†’ QtGui β†’ GLES β†’ EGL and that's where a warning is likely thrown when CMake tries to compile the 'check_cxx_source_compiles' block in FindEGL.cmake.

Either CMAKE_CXX_FLAGS shall be less strict or it shall be moved after finding qcoro's build dependencies.

Add support for `Generator<void>`

Generator<void> is useful for creating a simple synchronous coroutine that can be paused and resumed with no other special functionality. As of now Generator<void> in a compile error.

Example usecase: a test driver function for testing a program that uses some sort of an asynchronous messaging mechanism

#include <QCoroGenerator>

struct Connection;
Connection* get_connection();
auto conn = get_connection();

struct Message;
Message currentMessage;

QCoro::Generator<void> test_driver()
{
    co_yield;
    check_message_ok(currentMessage);
    conn->sendMessage(...);
    co_yield;
    check_message_ok(currentMessage);
    conn->sendMessage(...);

    //
    // ...
    //

    co_return;
}

struct App;
App* create_app(Connection*);

int main(int argc, char* argv[])
{
    auto driver = test_driver();
    auto it = driver.begin();

    auto app = create_app(conn);

    connect(conn, &Connection::messageReceived, [&] (const auto& msg) {
        currentMessage = msg;
        ++it;
        if (it == driver.end()) {
            app->exit(0);
        }
    });

    app->exec();
}

Update to aqtinstall 2.x

There's a new major version of aqtinstall, which is incompatible with the old one, so some changes to the GH Actions script to install Qt are needed.

Currently we are frozen on 1.2.x, but there's a change that it might break if Qt changes something on their side and we will need latest version of aqtinstall anyway - better update it now ;-)

QML support

So far QCoro can only be used in C++ code. However, it should be possible to return QCoro::Task<T> from a QObject's invokable method that can be called from QML.

Unfortunately, we are unable to extend the QML engine in such a way to support "async" and "await" keywords to duplicate the ES8 Promise/Async/Await API. However, we should still be able to wrap QCoro::Task<T> into some QML-friendly wrapper that can expose the existing .then() continuations, so that it's possible to asynchronously handle a C++ coroutine result in QML.

Can't find Threads if compiled with Clang

When compile qcoro 0.3.0 with LLVM/Clang 13.0.0 I see this configuration error:

DEBUG util.py:623:  -- Looking for C++ include pthread.h
DEBUG util.py:623:  -- Looking for C++ include pthread.h - not found
DEBUG util.py:621:  CMake Error at /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
DEBUG util.py:621:    Could NOT find Threads (missing: Threads_FOUND)
DEBUG util.py:621:  Call Stack (most recent call first):
DEBUG util.py:621:    /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
DEBUG util.py:621:    /usr/share/cmake/Modules/FindThreads.cmake:238 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
DEBUG util.py:621:    CMakeLists.txt:61 (find_package)
DEBUG util.py:623:  -- Configuring incomplete, errors occurred!

Full build log: https://file-store.openmandriva.org/api/v1/file_stores/432e3f9a77df2b7bc68ea7c1edbb36ce6018db68.log?show=true

Details:
OS: OpenMandriva Cooker
Compiler: LLVM/Clang 13.0.0
LTO: Enabled

I tried linking -pthread but was same.

Only compilation with GCC fixed the problem.

The problem is that in Mandriva we try to make sure that every (if possible) package is built with Clang.
So it would be great if a Clang compilation would be possible.

Stability policy?

We'd like to use QCoro in Plasma, but before we do that we'd like to know what kind of stability (in terms of API/ABI etc) we can expect from new QCoro versions.

We can probably live without ABI stability, but a (reasonably) stable API would be appreciated.

The readme says "This is a rather experimental library that helps me to understand coroutines in C++." Is that still accurate or has the project matured since writing that?

qcoroprocess test failed on 0.4.0

+ /usr/bin/ctest --output-on-failure --force-new-ctest-process -j4
Test project /builddir/build/BUILD/qcoro-0.4.0/redhat-linux-build
      Start  1: test-qtimer
      Start  2: test-qcoroprocess
      Start  3: test-qcorosignal
      Start  4: test-task
 1/13 Test  #3: test-qcorosignal .................   Passed    0.31 sec
      Start  5: test-testconstraints
 2/13 Test  #5: test-testconstraints .............   Passed    0.01 sec
      Start  6: test-qfuture
 3/13 Test  #1: test-qtimer ......................   Passed    0.70 sec
      Start  7: test-qdbuspendingcall
 4/13 Test  #6: test-qfuture .....................   Passed    0.91 sec
      Start  8: test-qdbuspendingreply
 5/13 Test  #7: test-qdbuspendingcall ............   Passed    1.02 sec
      Start  9: test-qcorolocalsocket
 6/13 Test  #4: test-task ........................   Passed    1.89 sec
      Start 10: test-qcoroabstractsocket
 7/13 Test  #2: test-qcoroprocess ................***Failed    4.02 sec
********* Start testing of QCoroProcessTest *********
Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 11.2.1 20210728 (Red Hat 11.2.1-1)), fedora 35
PASS   : QCoroProcessTest::initTestCase()
PASS   : QCoroProcessTest::testStartTriggers()
PASS   : QCoroProcessTest::testStartNoArgsTriggers()
FAIL!  : QCoroProcessTest::testStartDoesntBlock() 'eventLoopResponsive' returned FALSE. ()
   Loc: [/builddir/build/BUILD/qcoro-0.4.0/tests/qcoroprocess.cpp(77)]
QWARN  : QCoroProcessTest::testStartDoesntBlock() QProcess: Destroyed while process ("true") is still running.
PASS   : QCoroProcessTest::testStartDoesntCoAwaitRunningProcess()
PASS   : QCoroProcessTest::testFinishTriggers()
PASS   : QCoroProcessTest::testFinishDoesntCoAwaitFinishedProcess()
PASS   : QCoroProcessTest::testFinishCoAwaitTimeout()
PASS   : QCoroProcessTest::cleanupTestCase()
Totals: 8 passed, 1 failed, 0 skipped, 0 blacklisted, 4012ms
********* Finished testing of QCoroProcessTest *********

      Start 11: test-qcoronetworkreply
 8/13 Test  #8: test-qdbuspendingreply ...........   Passed    3.12 sec
      Start 12: test-qcorotcpserver
 9/13 Test #12: test-qcorotcpserver ..............   Passed    0.51 sec
      Start 13: test-testhttpserver
10/13 Test #13: test-testhttpserver ..............   Passed    1.51 sec
11/13 Test  #9: test-qcorolocalsocket ............   Passed    5.05 sec
12/13 Test #10: test-qcoroabstractsocket .........   Passed    5.05 sec
13/13 Test #11: test-qcoronetworkreply ...........   Passed    4.52 sec

92% tests passed, 1 tests failed out of 13

Total Test time (real) =   8.54 sec

The following tests FAILED:
          2 - test-qcoroprocess (Failed)
Errors while running CTest

Initial release?

I'd like to use qcoro in my (KDE) projects. Distros hate shipping stuff from git main branch, so it would be nice to have some form of release. A git tag should do, a downloadable tarball would be even better.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.