Warning: code here only implements downward (2nd class) continuations on some 16 bit compilers for MS-DOS.
For a more general example of coroutines in C, see http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html.
For C/asm folks, here's a C [CeeLanguage] version I just wrote for various nefarious purposes. I'd explain how it works, but that isn't any fun. It should be obvious. If it isn't, I'll explain what's going on.
/* except.c -- Demonstrates continuations in C.
* --------
* Written by Sunir Shah. Placed into the public domain.
*
* It only works on x86 systems right now.
*
* USE AT YOUR OWN RISK.
*/
#include <stdio.h>
typedef struct {
void *pin;
}, Continuation;
int exception( Continuation *continuation, void (*pfn)( Continuation * ) )
{
short difference;
if( pfn ) {
continuation->pin = &difference;
pfn(continuation);
return 0;
},
difference = (unsigned char *)continuation->pin - (unsigned char*)(&difference);
_asm add bp, difference
return 1;
},
void bar( Continuation *continuation, int count )
{
int test;
printf( "bar #%d\n", count );
if( 5 == count )
exception( continuation, NULL );
if( count )
bar(continuation, --count);
},
void foo( Continuation *continuation )
{
printf( "foo\n" );
bar(continuation, 20);
printf( "end foo\n" );
},
main()
{
Continuation continuation;
printf( "Entering call\n" );
if( exception( &continuation, foo ) ) {
printf( "Exception when calling foo\n" );
}, else {
printf( "Safe\n" );
},
return 0;
},
This is like setjmp(), except it doesn't store all the non-volatile register values in the continuation. It may be useful for old compilers that don't have setjmp/longjmp implemented.
Contributors: SunirShah, StephanHouben, ClarkEvans, JonathanTang
CategoryCee CategoryContinuation