Javatpoint Logo
Javatpoint Logo

Coroutines in C++

In this article, we will discuss the coroutines, uses, implementation, examples, and outputs.

What are Coroutines?

Coroutines in C++ are a type of control structure where the control flow is transmitted from one routine to another without stopping. The C++20 version introduces the C++ coroutine feature. Coroutine is a method that can stop the execution from needing to be resumed later. Coroutines are used at various phases of development in a similar way to the non-concurrent execution of code with a set of valid sequential codes in place. Because C++ coroutines have a stackless behaviour, this function gives the result to the caller. It continues the specified coroutine, which is once more stored in the already declared isolated region or stack.

Why are C++ Coroutines used?

You can read a record step by step at each line, which is OK, or you can read into a few key and relevant pieces of information to describe it. It is also feasible to load all of the huge material into RAM. However, it is not advised for applications that frequently use large text files, such as MS Word and text editors.

Donald Knuth introduced a solution to this issue in computer programming to address it. According to Donald Knuth, we can entirely do away with the stack concept. We don't need to allow the caller or caller to go through any processes. Simply think of them as cooperating equals.

Coroutine implementation in C++

The following two conditions must be met in order to implement C++ coroutines:

  • Resuming control in the previous state
  • create persistent data using calls

Static variables can be used to resolve the issue, as mentioned above. But how do you remember that the state also goes back to the same execution state as a moment ago, i.e., the lines of code following the return or the loop. Here, the GOTO statements are applicable. Let's look at the code below.

Let's take an example to understand how we can use the coroutines in C++.

Code:

Output:

control at main :1
control at range
control at main :2
control at range
control at main :3
control at range
control at main :4
control at range

Explanation:

In this example, many return justifications have been defined inside the for loop. We essentially return to a different state each time, executing the programme if it is configured to do so. This method mimics the Python function known as the range function. The C++ coroutine concept is also the foundation for that Python function.

How do Coroutines operate in C++?

Coroutines in C++ operate as detailed below.

When the primary execution of a C++ coroutine is finished, it can still be continued later. The main function is mostly called by C++ coroutines, after which the data is saved elsewhere. Coroutines are functions, and we must associate their data type with them for them to function.

The C++ coroutines are excellent coroutines because they are always coupled with variable arguments and return statements. But there are still some limitations. The main function, constant expression function, constructors, and destructors, cannot create a flawless coroutine.

Execution paradigm using a coroutine:

Two things are related to a C++coroutine. The promise object is the first, and the coroutine object is the second. A promise object is an object that gives a synchronisation point and can contain a value that can be obtained by any future a=object (often another thread). Additionally, a heap is used with the coroutine state when it is made available in an efficient way. The following characteristics apply to the state object:

Options for parameters.

  • The local variables and the temporary variables have a limited time stamp and scope up until the current suspension point.
  • Promise manipulable items therein.
  • We represent the appropriate state and value of the local variables to know where to resume and continue the execution.

Handles for coroutines:

We use the coroutine handles whenever we need to build and execute code outside of the coroutine frame. We employ the non-use handling handlers of the coroutine hold to resume the coroutine's execution and simultaneously remove the C++ coroutines from the frame. A C++coroutine handle is somewhat comparable to a c pointer, which can be easily copied, but we lack a destructor to clear the memory it has taken up. Therefore, we must utilize the coroutine_handle:: destroy method to terminate the coroutine and prevent memory leaks. The coroutine handler that was pointing to the deleted coroutine is removed when the coroutine is destroyed. Now that it points to a garbage value, the coroutine handler will no longer function when called.

standard return object:

The C++ coroutine returns an object with a nested type::promise_type as its return type. A method called r get_return_object, which returns an outer object of type r, should be included in the r::promise_type. A coroutine function is the result of the get_return_object function.

The promise object:

A promise type instance exists in the coroutine state. We can add a field called value to transfer the values from the coroutine to the main function. The coroutine handle is kept as std::coroutine_handleReturnObject3::promise_type> rather than being converted to a std::coroutine_handle>.

The operator co_yield:

The co_yield operator returns the value it yielded from the expression to the caller. One of the most popular components of the resumable generator functions, it suspends the running coroutine.

The operator co_return:

A coroutine comes to a close when the co_return operator is used. Signalling can be done in one of three ways.

  1. The value e can be returned using Co_return e.
  2. The co_routine can utilise the co_return operator to indicate the end of a coroutine without a final value.
  3. Similar to the preceding point, we may use the co_return operator to fall off the end of the function.

Things to Keep in Mind When Using Coroutines:

We should never forget the following are some key considerations for using C++ coroutines.

  • The sole operator available to C++ coroutines is co_return; return is not supported.
  • Both the use of varargs and the use of a constexpr are prohibited.
  • Neither a constructor nor a destructor are allowed.
  • The main function cannot also contain the coroutines.
  • We should use parameters by value when utilising C++ coroutines to be on the safe side and prevent dangling references.

Reference parameters and Coroutines:

Implementing C++ coroutines prevents the full call stack from being saved when the coroutine is suspended. It only stores the local variable. Stack complete coroutines are one type of implementation of the coroutine. On the other side, we have a stack-less coroutine that saves and restores the full call stack. Similar to any other asynchronous parameter, a coroutine reference parameter requires a reference parameter that the calling object must supply. By doing this, it is made sure that the linked object will endure for the duration of the object.

Code:

Output:

-4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 

1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96 101 106 111 116 121

Example 2:

In this example, the values returned from the output were stored using C++ coroutines.

Code:

Output:

fut_1.get(): 2022

Conclusion

  1. Coroutines in C++ are a type of control structure where the control flow is transmitted from one routine to another without stopping.
  2. After that, the C++ coroutine was introduced starting, with C++11.
  3. The stack-based operation used by the C++coroutine.
  4. Even after the primary execution is finished, the C++ coroutines are functions that can be continued later.
  5. The promise object and the coroutine object are two things connected to C++ coroutines.
  6. The coroutine handle is used to halt or pause the coroutine that is running right now.






Youtube For Videos Join Our Youtube Channel: Join Now

Feedback


Help Others, Please Share

facebook twitter pinterest

Learn Latest Tutorials


Preparation


Trending Technologies


B.Tech / MCA