« Previous entry | Next entry » Browse > Snippets

Skip to comments (1) Reentrant coroutines in C++
Posted by Erik on Jan 09 2006 @ 16:14  :: 3113 unique visits

My previous post Simple coroutines in C showed some macro's to turn normal C/C++ funtions into coroutines. A disadvantage of these coroutines was that they weren't reentrant. I have found two ways to fix this problem:
  1. Adding an extra context parameter to the function. This would require some modification in the body of the function, e.g. context->i instead of i. It would also require the caller of the function to create and remember the context. An advantage is that this method works in both C and C++.
  1. Overloading the function application operator of a class and using the class as the context. This only works in C++ but requires minimal code modifications.

Here I will only discuss the second method because I find it a nicer way to solve the problem.

First thing is that the coroutine macro's need a little modification.
The cr_start macro is divided into 3 seperate macro's:
CODE: CPP
// old cr_start
#define cr_start()   static int __s = 0; switch (__s) { case 0:

// new macro's
#define cr_context   int __s;
#define cr_init()    __s = 0;
#define cr_start()   switch (__s) { case 0:
#define cr_return(x) { __s = __LINE__; return x; case __LINE__: ; }
#define cr_end()     { break; default: for (;;) ; } } __s = 0;
 


Here is an example of the foobar() function from my previous post about coroutines as a reentrant coroutine:
CODE: CPP
class foobar_f {
private:
    cr_context;

    // place the variables which need to be remembered between calls here.
    int i;

public:
    foobar_f(void) {
        cr_init();
    }

    // overloading the function application operator "()"
    int operator () (void) {
        cr_start();

        for (i = 0; i < 1337; i++) {
            cr_return(i);
        }

        cr_end();
    }
};


The usage of the coroutine requires a little modification from the caller's side:
CODE: CPP
// create a function object, sometimes (incorrectly) called functor.
foobar_f foobar;

printf("%d\n", foobar()); // prints 0
printf("%d\n", foobar()); // prints 1
printf("%d\n", foobar()); // prints 2
 


One important note I forgot in my previous post


You can't use a the cr_return macro inside the case of one of your own switch statements!
This because coroutines are implemented using a switch statement and cr_return uses a case statement of it's own.

1 comment posted so far
Add your own »

1. On Aug 09 2008 @ 04:53 priya wrote:

Anyone bought from www.belrion.com before ? heard they are a paypal world seller and are macfee secured. Appreciate some feedback from anyone ^^
<a href  = http://www.belrion.com/en/ffxi.htm > buy ffxi</a><br>
<a href  = http://www.belrion.com/en/eq.htm> buy eq flat </a><br>
<a href  = http://www.belrion.com/en/wow.htm> cheap wow gold</a><br>
<a href  = http://www.belrion.com>  LOTR gold</a><br>
<a href  = http://www.belrion.com/en/sell.htm>buy aoc gold</a><br>
<a href  = http://www.belrion.com/en/l2.htm> buy L2 adena</a><br>
<a href  = http://www.belrion.com/en/gamesvr.php?cid=1&gid=3&sid=10 >buy gils</a><br>
<a href  = http://www.belrion.com/en/eq.htm >cheap gold wow</a><br>

Add a new comment

Name:
Password: (leave empty for anonymous comment)
 
View formatting tags Comment: