« Previous entry | Next entry » Browse > Snippets
Skip to comments (9)
Simple coroutines in C
Posted by Erik on Jan 06 2006 @ 11:27 :: 3396 unique visits
Invalid way to write a simple generator in C/C++:CODE: C
int foobar() {
int i;
for (i = 0; i < 1337; i++) {
return i;
}
}
int i;
for (i = 0; i < 1337; i++) {
return i;
}
}
Wouldn't it be cool if this was valid?
Well it is! With coroutines. Coroutines are functions in which you can return from and next time continue at the spot you last returned from.
4 macro's used to simplify the creation of coroutine:
CODE: C
#define cr_start() static int __s = 0; switch (__s) { case 0:
#define cr_returnv { __s = __LINE__; return; case __LINE__: ; }
#define cr_return(x) { __s = __LINE__; return x; case __LINE__: ; }
#define cr_end() } __s = 0;
#define cr_returnv { __s = __LINE__; return; case __LINE__: ; }
#define cr_return(x) { __s = __LINE__; return x; case __LINE__: ; }
#define cr_end() } __s = 0;
The above code written as a coroutine:
CODE: C
int foobar() {
static int i;
cr_start();
for (i = 0; i < 1337; i++) {
cr_return(i);
}
cr_end();
}
foobar(); // will return 0
foobar(); // will return 1
static int i;
cr_start();
for (i = 0; i < 1337; i++) {
cr_return(i);
}
cr_end();
}
foobar(); // will return 0
foobar(); // will return 1
How does it work?
The above code with macro's expanded, and made a little more readable:
CODE: C
int foobar() {
static int i;
static int __s = 0;
switch (__s) {
case 0:
for (i = 0; i < 1337; i++) {
__s = 42;
return i;
case 42:
}
}
__s = 0;
}
static int i;
static int __s = 0;
switch (__s) {
case 0:
for (i = 0; i < 1337; i++) {
__s = 42;
return i;
case 42:
}
}
__s = 0;
}
Note: I replaced the __LINE__ macro with 42, normally your compiler would replace it with the current line number.
As you can see coroutines use a little trick in C which most people aren't aware of. You can put the case of a swith inside the body of a for/while that starts inside that switch. So the second time the function is called, the switch jumpes inside the for loop and i won't be reset to 0.
Another more simpler example:
CODE: C
void count(void) {
cr_start();
printf("first\n");
cr_returnv;
printf("second\n");
cr_returnv;
printf("third\n");
cr_end();
}
count(); // print "first"
count(); // print "second"
count(); // print "third"
count(); // print "first"
cr_start();
printf("first\n");
cr_returnv;
printf("second\n");
cr_returnv;
printf("third\n");
cr_end();
}
count(); // print "first"
count(); // print "second"
count(); // print "third"
count(); // print "first"
When you expand the macro's here you will see that it's just a simple switch with a static variable.
Reentrant coroutines
As you might have noticed coroutines aren't reentrant nor thread-safe. This can be fixed by making the macro's a litte more complex and adding one extra argument to the functions.
Edit 9-1-2006:
My post about reentrant coroutines
Original work from: Simon Tatham
9 comments posted so far
Add your own »
2. On Jan 06 2006 @ 14:54 Erik wrote:
That's why I'll post the reentrant coroutines which don't use the global context soon.3. On Jan 08 2006 @ 21:42 Erik wrote:
If you are using Visual Studio you may get an:CODE: OTHER
error C2051: case expression not constant
This is because of a Visual Studio feature called Edit and Continue. Edit and Continue enables you to modify your code (with some limitations) while you are dubugging your program and apply those changes without having to end the debug session and rebuild your program.
Because of this the __LINE__ macro isn't a constant (because you could insert new lines before it) and you get this error.
In Visual Studio 6.0 you can disable Edit and Continue the folloing way:
- Open your Project Settings (Alt+F7).
- Go to the C/C++ tab
- Change Debug info from "Program Database for Edit and Continue" to "Program Database"
I don't know how to disable it for other versions of Visual Studio.
Another usage for coroutines
user-level yield like scheduling:
CODE: C
void userthread1() {
cr_start();
for (;;) {
// do stuff
cr_returnv;
}
cr_endv();
}
void userthread2() {
cr_start();
for (;;) {
if (condition) {
// do stuff
cr_returnv;
}
// do more stuff
cr_returnv;
}
cr_endv();
}
int main(int argc, char* argv[]) {
for (;;) {
userthread1();
userthread2();
}
}
cr_start();
for (;;) {
// do stuff
cr_returnv;
}
cr_endv();
}
void userthread2() {
cr_start();
for (;;) {
if (condition) {
// do stuff
cr_returnv;
}
// do more stuff
cr_returnv;
}
cr_endv();
}
int main(int argc, char* argv[]) {
for (;;) {
userthread1();
userthread2();
}
}
5. On May 09 2009 @ 19:05 maryzheng wrote:
TradeTang is your dream come true for all your wholesale products shopping needs. Our inexpensive selection of quality wholesale merchandise is out of this world. We sell everything you can imagine from candles to baby products and children's toys to pet supplies. If you are buying bulk merchandise for an apparel shop, then our amazing line of clothes, jewelry, flip-flops and shoes are perfect for you. We also carry incredible wholesale supplies that would be great at a home improvement or China Wholesale.6. On May 19 2009 @ 09:35 guest wrote:
Find louis vuitton handbag and louis Louis Vuitton Handbags , louis vuitton wallet and louis vuitton purse items on Louis Vuitton Store Browse a huge selection of LV Handbags Louis Vuitton is luxury gifts, French fashion, the replica Louis Vuitton Store is woman best friend. With Louis Vuitton Discover real Louis Vuitton bags, Vuitton accessories and the latest handbag lines. Join the biggest active Louis Vuitton enthusiast community on the web todayUGGs is a brand that is all about luxury and comfort for everyday life. Only the finest quality materials are used to create UGG Boots. Provide UGG Women Boots,UGG Man Boots,UGG Kids Boots.
UGG Australia is the largest distributor of Grade-A sheepskin.
Find Women's UGGs, Men's UGG Boots, and Kids UGGs on Sale all made with ... UGG Store include Discount UGG UGG Classic Tall,UGG Classic Short
Louis Vuitton is luxury gifts, French fashion, the replica Louis Vuitton Handbag is woman best friend.Monogram Groom.
Offers Discount Louis Vuitton handbags and Louis Vuitton bags and all other designer handbags,free global fast shipping,low price and top quality.Monogram Jokes,Monogram Suede cheap Louis Vuitton
Louis Vuitton.
Looking For Gucci Shoes ? Gucci Store provide gucci Mens shoes,gucci Womens shoes
Wonderful Gucci shoes sale Gucci men's shoes and Gucci women's shoes at discount Gucci Shoes prices.
cheap gucci Shoes
Gucci Shoes and gucci clothing Spring - Summer 2009, Prada Shoes and prada clothing from the Latest Collection 2009 and Dolce Gabbana Clothing 2009
Gucci Loafers
Gucci Sneakers
UGGs
Louis Vuitton Handbags
Gucci Shoes
Louis Vuitton
UGG Boots
Louis Vuitton Handbags
gucci shoes
Monogram Groom
Discount Louis Vuitton
UGG Boots
Louis Vuitton handbags
7. On Jun 25 2009 @ 04:14 guest wrote:
DVD Audio RipperFree DVD Audio Ripper
DVD Audio Ripper for Mac
DVD to MP4 Converter
DVD to MP4 Converter for Mac
DVD to iPod Converter
free DVD to iPod Converter
DVD to iPod Converter for Mac
DVD Ripper
Diablo 2 CD Key
Diablo 2 CD Keys
Free DVD Ripper
DVD Ripper for Mac
NFL Jerseys
Scoccer Jerseys
Hockey Jerseys
MLB Jerseys
NHL Jerseys
Nike Sneakers
8. On Jul 14 2009 @ 04:03 guest wrote:
buy wow goldmy wow power leveling
buy wow gold
good wow power leveling
BUY wow gold
my wow power leveling
CHEAP rs gold
cheap wow power leveling
CHEAPEST lotro gold
MY aion gold
buy wow gold
cheap wow gold
CHEAPEST wow gold
1. On Jan 06 2006 @ 13:28 l0ne wrote:
Cool! And pretty ingenious too. But, due to the 'static' keyword, the whole thing has a global context, which is no-no for oh-so-many-apps...