Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
What is Coroutine?
3.
C++ Coroutine Supporters
3.1.
awaitable
3.2.
use_awaitable Completion Token
3.3.
co_spawn Function
4.
Executing Program Using C++ Coroutine
5.
Error Handling in Coroutines
6.
Frequently Asked Questions
6.1.
What are completion tokens?
6.2.
How can we cancel the created co_spawn?
6.3.
What is the main use of coroutines?
6.4.
How many coroutines can be run at one time?
7.
Conclusion
Last Updated: Mar 27, 2024
Medium

C++ Coroutines Support

Introduction

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?

Introdution to C++ Coroutines Support

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.

Also read, Abstract Data Types in C++

What is 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:

  1. Stackful Coroutines
  2. 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. 

Selecting C++ Language Standard

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, executorninja 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

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 use as_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.

Also see, Application of Oops

Frequently Asked Questions

What are completion tokens?

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.

Happy Coding!

Live masterclass