c / expert
Snippet
Zustandsbehaftetes Re-entrant Coroutine-Trampolin über Switch-Fallthrough-Zustandsautomat
Dieses Beispiel zeigt stapellose Coroutinen (Stackless Coroutines) in C basierend auf Zustandsbeharren durch switch-Anweisungen. Unter Nutzung von Makro-Expansion und der __LINE__ Präprozessor-Direktive wird die Ausführung beim erneuten Funktionsaufruf an der exakten Stelle des letzten Yield-Punkts fortgesetzt.
snippet.c
c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>typedef struct {int state;int index;} GeneratorState;#define COROUTINE_BEGIN(ctx) switch((ctx)->state) { case 0:#define COROUTINE_YIELD(ctx, val) do { (ctx)->state = __LINE__; return (val); case __LINE__:; } while(0)#define COROUTINE_END(ctx) default: (ctx)->state = -1; return -1; }int generate_fibonacci(GeneratorState *ctx) {static int a = 0, b = 1;COROUTINE_BEGIN(ctx);while (ctx->index < 5) {int next = a + b;a = b;b = next;ctx->index++;COROUTINE_YIELD(ctx, a);}COROUTINE_END(ctx);}
Erklärung
1
#define COROUTINE_BEGIN(ctx) switch((ctx)->state) { case 0:
Öffnet einen Switch-Block, der direkt zum gespeicherten Zustandsschlüssel springt.
2
#define COROUTINE_YIELD(ctx, val) do { (ctx)->state = __LINE__; return (val); case __LINE__:; } while(0)
Speichert die aktuelle Zeile als Wiederaufnahme-Zustand, gibt einen Wert zurück und setzt ein case-Label.
3
COROUTINE_YIELD(ctx, a);
Gibt die Steuerung unter Beibehaltung der Ausführungsposition an den Aufrufer zurück.
4
#define COROUTINE_END(ctx) default: (ctx)->state = -1; return -1; }
Schließt das Trampolin-Konstrukt ab und setzt den Zustand nach Beendigung auf ungültig.