Last active
August 29, 2015 14:07
-
-
Save gatlin/ca1e004fb923f187191f to your computer and use it in GitHub Desktop.
Simple, toy coroutine mechanism in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Simple coroutine mechanism in C | |
* | |
* Inspired by / stolen from: | |
* | |
* http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html | |
* | |
* I found this very educational and wanted to publish a simple demonstration. | |
* | |
* Usage: | |
* | |
* $> gcc -o coro_switch coro_switch.c | |
* $> ./coro_switch | |
* | |
* Explanation: A function in C can allocate so-called static values, whose | |
* values are preserved between calls to the function. | |
* | |
* We initialize a static integer `__coro_state` to be 0 and use it as the | |
* argument to a switch statement. To yield a value `__coro_state` is set to an | |
* arbitrary but unique value (the source line number, provided by __LINE__) | |
* and the immediate next statement is a case expecting *precisely* that value. | |
* | |
* The next time the function is called, `__coro_state` will be different and | |
* we will switch directly to immediately after where we yielded. | |
* | |
* TODO: | |
* 1. Make this threadsafe by making all static variables part of some context | |
* struct. | |
*/ | |
#include <stdio.h> /* For printf() */ | |
#define coro_start static int __coro_state=0; switch(__coro_state) { case 0: | |
#define yield(X) do { __coro_state=__LINE__; return X; \ | |
case __LINE__:; } while (0) | |
#define coro_finish } | |
int zero_to_nine(void) { | |
static int i; | |
coro_start; | |
for (i = 0; i < 10; i++) { | |
yield(i); | |
} | |
coro_finish; | |
} | |
int ten_to_nineteen(void) { | |
static int i; | |
coro_start; | |
for (i = 10; i < 20; i++) { | |
yield(i); | |
} | |
coro_finish; | |
} | |
int main(int argc, char **argv) { | |
int i; | |
int num_yielded; | |
for (i = 0; i < 20; i++) { | |
if (i % 2 == 0) { | |
num_yielded = zero_to_nine(); | |
} | |
else { | |
num_yielded = ten_to_nineteen(); | |
} | |
printf("Received: %d\n", num_yielded); | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment