Coroutines in C/C++

What are coroutines?
Coroutines are general control structures where flow control is cooperatively passed between two different routines without returning.
If you have used Python or C#, you may know that there is a keyword called yield that allows loop back and forth between the caller and the called function until the caller is not done with function or the function terminates because of some logic it is given.

Sample Python3 code of yield

filter_none

edit
close

play_arrow

link
brightness_4
code

# A Python program to generate numbers in a 
# range using yield
   
def rangeN(a, b):
    i = a
    while (i < b):
        yield i
        i += 1  # Next execution resumes 
                # from this point    
  
for i in rangeN(1, 5):
        print(i)

chevron_right


Output :



1
2
3
4
5 

This code demonstrates how does the yield works and gives a brief idea about how the control is changed between the caller and callee.

Why Coroutines are needed?
To read a file and parse it while reading into some meaningful data, you can either read step by step at each line, which is fine. You may also load the entire content in memory, which won’t be recommended for large text cases e.g text editors like Microsoft Word or in modern systems just use Pipes.

In The Art of Computer Programming, Donald Knuth presents a solution to this sort of problem. His answer is to throw away the stack concept completely. Stop thinking of one process as the caller and the other as the callee, and start thinking of them as cooperating equals.
So we can now try and see how to achieve the same in C.

function read():
   /* reads the content in the desired number 
      of steps and returns back control to parser
      but saves its own state of function. */

function parse():
   a = read()
   while (a)
   {
       // do something
       a = read()
   }

Well, in practice this structure looks very similar to the caller-callee structure of C. But what we require here is that the reader must remember its state. It must remember where it was last time when it did the job and should also be re-settable.

How to implement Coroutines in C?
The challenge is to have coroutines in C language which is itself a stack based language i.e in every response to a function call in C language there is a stack being initialized that keeps track of all its variables and constants, and gets destroyed when the function call ends.

filter_none

edit
close

play_arrow

link
brightness_4
code

int read(void
{
    int i;
    for (i = 0; i < 10; i++)
        return i;   /* Well on the first run itself 
                      the function will be destroyed */
}

chevron_right


We need to do two things:

  1. Resume control to its last state
  2. Make data persist through calls

Both of these above problems should be solved by the use of static variables. But how to remember the state and also return back to a the same execution state as before i.e., the lines of code after return or the loop. We can use GOTO statements. Which is not recommended generally. Here, we can try something called the Duff’s device.

So we finally move on the solution code.

filter_none

edit
close

play_arrow

link
brightness_4
code

// C program to demonstrate how coroutines
// can be implemented in C.
#include<stdio.h>
  
int range(int a, int b)
{
    static long long int i;
    static int state = 0;
    switch (state)
    {
    case 0: /* start of function */
        state = 1;
        for (i = a; i < b; i++)
        {
            return i;
  
        /* Returns control */
        case 1:; /* resume control straight
                    after the return */
        }
    }
    state = 0;
    return 0;
}
  
// Driver code
int main()
{
    int i; //For really large numbers
  
    for (; i=range(1, 5);)
        printf("control at main :%d\n", i);
  
    return 0;

chevron_right


Output :

control at range
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 

The solution uses our understanding of Duff’s device and has it play with it. We can now essentially have multiple return statements inside the for loop and each time we return to a different state of execution if it’s programmed to do so. This implementation only mimics the range function of python which is also based of coroutine since it returns generator objects as of Python3.

Source :
Coroutines in C by Simon Tatham

This article is contributed by Rajat Kanti Bhattacharjee. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up
Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.