danvratil / qcoro Goto Github PK
View Code? Open in Web Editor NEWC++ Coroutines for Qt
Home Page: https://qcoro.dvratil.cz
License: MIT License
C++ Coroutines for Qt
Home Page: https://qcoro.dvratil.cz
License: MIT License
Some time during May something has changed in clang that causes qcorotcpservertest to fail under ASAN.
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> ...);
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?
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.
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.
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
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
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.
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.*)
https://aur.archlinux.org/packages/qcoro-git/
Thx for the great library, I packaged it for Arch linux users.
I'll try to make it to your Akademy talk tomorrow
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...
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.
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)
}
Add a header that contains forward-declarations for common public QCoro types (Task, generators)
See the discussion in #70 for details.
Build and install Qt 5 and Qt 6 version in a single pass. It will help GNU/Linux package maintainers.
Now we need to perform two separate builds.
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;
}
+ /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
There are currently no tests for QCoroImageProvider
, someone should fix that ;-)
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.
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 !
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)
Lines 23 to 33 in 353aacf
operator co_await()
cause an error.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()
The include-markdown plugin seems broken, nothing gets included and the entire page is broken.
It seems to work in mkdocs serve
but is broken in production build.
List of broken pages:
https://qcoro.dvratil.cz/reference/core/qfuture/
https://qcoro.dvratil.cz/reference/core/qprocess/
https://qcoro.dvratil.cz/reference/core/qthread/
https://qcoro.dvratil.cz/reference/network/qabstractsocket/
https://qcoro.dvratil.cz/reference/network/qnetworkreply/
https://qcoro.dvratil.cz/reference/network/qtcpserver/
https://qcoro.dvratil.cz/reference/dbus/qdbuspendingcall/
https://qcoro.dvratil.cz/reference/dbus/qdbuspendingreply/
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.
...
[ 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.
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();
}
Don't specify shared library in add_library, so users can use BUILD_SHARED_LIBS
to control static or shared library.
Line 17 in 353aacf
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.
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;
}
...
}
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;
}
...
}
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.
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.
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>;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 ;-)
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.
For example, send a command via serial port; await its response but need to cancel it due to timeout.
/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.
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?
Having soversioned libraries is important for Linux distributions (because different versions of shared libraries may be installed in parallel).
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.
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... :)
Add wrappers for QWebSocket and QWebSocketServer.
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.
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?
Based on #44 it's clear we need to fix feature detection at config time.
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).QT_CONFIG(dbus)
to adjust default QCORO_WITH_QTDBUS
valueQT_CONFIG(network)
to adjust default QCORO_WITH_QTNETWORK
valueQT_CONFIG(process)
to detect whether Qt is built with QProcess support (#44)QT_CONFIG(future)
to detect whether Qt is built with QFuture supportQT_CONFIG(localserver)
to detect whether Qt is built with QLocalServer support (for QLocalSocket)QT_NO_EXCEPTION
to detect whether Qt is built with exception support (#28)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.
With the latest clang-cl, it reports errors like below:
qcoro\qcorotask.h(615,13): error: cannot use 'try' with exceptions disabled
If C++ EH is enabled, errors disappeared.
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.
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.
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.
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
Else the
include(CheckSourceCompiles)
Will fail (and cmake do not explain why)
https://cmake.org/cmake/help/latest/module/CheckSourceCompiles.html
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
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.