Do you know that C++ provides a special function that allows suspending the execution of the program and can resume later? Do you know about stackful and stackless coroutines?
In this article, we will discuss about C++ Coroutines. We will discuss how Coroutines supports programming. We will see how co_spawn, awaitable, and use_awaitable are used with the help of an example. We will also learn about Stackful Coroutines and Stackless Coroutines. Moving forward, let’s first understand the coroutine.
The Coroutine allows suspending execution of the program and can be resumed later. For using the C++ Coroutines, we must include the asio/coroutine.hpp header in our program. There are two types of coroutines:
Stackful Coroutines
Stackless Coroutines
The stackful coroutines have their own stack that is used to process function calls. In stackful coroutines, there is a high-level spawn() function that is responsible for running stackful coroutines. This function allows the implementation of asynchronous logic in a synchronous manner.
Stackless coroutines also allow the implementation of asynchronous logic in a synchronous manner.
C++ Coroutine Supporters
There are mainly three coroutine supporters in C++, which helps in facilitating the program. They are:
awaitable
use_awaitable completion token
co_spawn function
Moving forward, let’s understand them one by one.
awaitable
An awaitable in C++ Coroutine is a first-class object that indicates completed or non-completed asynchronous operations. The awaitable waits until the asynchronous operation is not completed. For using awaitable, we must include the asio/awaitable.hpp header in our program.
use_awaitable Completion Token
The use_awaitable completion token helps in determining the coroutine that is currently executing. This token can be passed to an asynchronous operation as a handler. For using the use_awaitable, we must include the asio/use_awaitable.hpp header in our program.
co_spawn Function
The co_spawn() function contains three arguments, the first argument is an executor, the second one is awaitable, and the third argument is a completion token. For including the co-spawn function, we must include asio/co_spawn.hpp. Let’s talk about these three arguments,
The first argument, which is an executor, helps in determining the context in which the coroutine is allowed to execute.
The second argument, which is awaitable, is the result of the function’s entry point.
The last and final argument is a completion token which helps in producing a completion handler.
Executing Program Using C++ Coroutine
To execute programs using C++ Coroutine, your C++ language standard option must be set as ISO C++20 Standard (/std:c++20). To set this, follow the below-mentioned steps:
After you have created your empty project in visual studio, right-click on project name -> Properties -> C/C++ Configuration -> All options -> C++ Language Standard and select C++20 Standard (/std:c++20) from the drop-down.
Now, you can use C++ coroutine features in your visual studio. Let’s understand C++ Coroutines supporters with the help of an example.
Code
#include <iostream>
#include <asio/co_spawn.hpp>
#include <asio/detached.hpp>
#include <asio/io_context.hpp>
#include <asio/awaitable.hpp>
#include <asio/use_awaitable.hpp>
using namespace std;
using asio::awaitable;
using asio::co_spawn;
using asio::detached;
using asio::use_awaitable;
namespace this_coro = asio::this_coro;
awaitable<void> ninja()
{
auto executor = co_await this_coro::executor;
std::cout << "Printing Executor ";
std::cout << executor << endl;
std::cout << "Inside awaitable ninja function" << endl;
}
int main()
{
asio::io_context io;
co_spawn(io, ninja(), detached);
std::cout << "Checking C++ Coroutines Supporters are working fine or not" << endl;
io.run();
std::cout << "Working Fine" << endl;
return 0;
}
Explanation
In the above code, we have performed asynchronous operations using C++20 coroutines. We have made a function named ninja which is awaitable and wrote code for getting the executor of this coroutine inside the ninja function. We are calling the co_spawn function, which is present inside our main function. The co_spawn function consists of three arguments, executor, ninja class, and a completion token. In the above code, we have used detached() as a completion token which is used to indicate the detached asynchronous operations. We printed few lines before and after entering the ninja function in order to check whether the program with C++ coroutine supporters is working fine or not.
Output
Error Handling in Coroutines
Error handling helps in capturing the errors during the execution of a program. It is required to handle the error to resume the execution of the program without any interruption. For performing explicit error handling in coroutines,we can useas_tuple and redirect_error instead of default exception-throwing.
The as_tuple helps in packaging the completion handler argument into a single tuple, which can be then returned. The header file for as_tuple is asio/as_tuple.hpp.
Whereas the redirect_error can be used in capturing the error into a variable. The header file for redirect_error is asio/redirect_error.hpp.
The completion tokens are passed in asynchronous operations. It is the final argument in an asynchronous operation.
How can we cancel the created co_spawn?
The created co_spawn can be cancelled by using asio::this_coro::cancellation_state. The cancellation of co_spawn will trigger an exception, for solving this exception this_coro::throw_if_cancelled can be used.
What is the main use of coroutines?
The main use of a coroutine is to suspend the execution of a program and then for resuming later.
How many coroutines can be run at one time?
The coroutines can not be run simultaneously, so we can run only one coroutine at a time.
Conclusion
In this article, we have learned a lot about C++ coroutines. We have discussed the main supporters of C++ coroutines. We have seen an example code for understanding C++ Coroutines supporters clearly. We have also discussed a bit about error handling in coroutines. To read more about Asio refer to below mentioned articles:
We hope this article has helped you in understanding about C++ Coroutines Support. You can read more such articles on our platform, Coding Ninjas Studio. You will find articles on almost every topic on our platform. Also, you can practice coding questions at Coding Ninjas to crack good product-based companies. For interview preparations, you can read the Interview Experiences of popular companies.