# QCoro C++ Coroutine Library for Qt5 and Qt6 --- ## Overview QCoro is a C++ library that provide set of tools to make use of C++20 coroutines in connection with certain asynchronous Qt actions. Take a look at the example below to see what an amazing thing coroutines are: ```cpp 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(); ``` This library has only one class and one function that the user must be aware of: the class is [`QCoro::Task`](reference/coro/task.md) and must be used as a return type for any coroutine that `co_await`s a Qt type. The function is [`qCoro()`](reference/coro/coro.md) and it provides coroutine-friendly wrappers for Qt types that have multiple asynchronous operations that the user may want to `co_await` (for example [`QProcess`](reference/core/qprocess.md)). All the other code (basically everything in the `QCoro::detail` namespace) is here to provide the cogs and gears for the C++ coroutine machinery, making it possible to use Qt types with coroutines. The major benefit of using coroutines with Qt types is that it allows writing asynchronous code as if it were synchronous and, most importantly, while the coroutine is `co_await`ing, the __Qt event loop runs as usual__, meaning that your application remains responsive. This is a rather experimental library that I started working on to better understand coroutines in C++. After reading numerous articles and blog posts about coroutines, it still wasn't exactly clear to me how the whole thing works, so I started working on this library to get a better idea about coroutines. ## Coroutines Coroutines are regular functions, except that they can be suspended and resumed again. When a coroutine is suspended, it returns sort of a promise to the caller and the caller continues executing their code. At some point, the caller can use the newly introduced `co_await` keyword to wait for the returned promise to be fulfilled. When that happens, the caller is suspended and instead the coroutine is resumed. This allows writing asynchronous code as if it were synchronous, making it much easier to read and understand. That's not all that coroutines can do, you can read more about it in the 'Coroutines' section of this documentation. ## Supported Qt Versions QCoro supports compiling for both Qt5 and Qt6. Minimum supported versions are: * Qt5 >= 5.15.2 * Qt6 >= 6.2.0 Pass `-DUSE_QT_VERSION=5` or `-DUSE_QT_VERSION=6` to CMake to force building QCoro with respective major version of Qt. QCoro will default to Qt6 when available and fallback to Qt5 otherwise. ## Supported Compilers This library requires a compiler that supports the Coroutine TS (obviously). Currently GCC, Clang and MSVC are supported. Officially supported compilers are: * GCC >= 11 (April 2021) * Clang >= 15 (September 2022) * MSVC >= 19.40 (Visual Studio 17 2022) * AppleClang >= 15.0.0 (Xcode 15.2) In both GCC and Clang, coroutine support must be explicitly enabled. ### GCC To enable coroutines support in GCC, add `-fcoroutines` to `CXX_FLAGS`. CMake: ```cmake set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines") ``` Alternatively, just use `qcoro_enable_coroutines()` CMake macro provided by QCoro to set the flags automatically. ### Clang In Clang coroutines are still considered experimental (unlike in GCC). Coroutines are enabled by adding `-fcoroutines-ts` to `CMAKE_CXX_FLAGS`. CMake: ```cmake set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts") ``` Alternatively, just use `qcoro_enable_coroutines()` CMake macro provided by QCoro to set the flags automatically. ### MSVC Coroutine support in MSVC is enabled automatically by CMake when C++20 standard is specified in `CMAKE_CXX_STANDARD`: ```cmake set(CMAKE_CXX_STANDARD 20) ```