Skip to content

Instantly share code, notes, and snippets.

@arms22
Last active January 2, 2016 08:49
Show Gist options
  • Save arms22/8278912 to your computer and use it in GitHub Desktop.
Save arms22/8278912 to your computer and use it in GitHub Desktop.
C言語用コルーチン。マイクロスレッドとかファイバーとかそんなやつ。Arduino用に極力シンプルに実装。gccのラベル拡張使ってるからgcc専用。実行結果:fiber test0 0 1 1 1 1 2 2 2 3 3 4 4 5 9
#ifndef FIBER_H
#define FIBER_H
#define FIBER_NEST_ENABLE 1
typedef void* fiber_t;
#define FIBER_INIT { ((void*)0) }
#define FIBER_LINE2(x) FIBER_LINE_ ## x
#define FIBER_LINE(x) FIBER_LINE2(x)
#if FIBER_NEST_ENABLE
static fiber_t __fb_softstack[8];
static fiber_t* __fb_sp = __fb_softstack;
#define __fb_return__ (*(__fb_sp - 1))
#define __fb_current__ (*(__fb_sp - 0))
#define fiber_run(fb) \
for(*__fb_sp++ = &&FIBER_LINE(__LINE__), *__fb_sp = (fb) \
;(fb) != &&FIBER_LINE(__LINE__) \
;(fb) = &&FIBER_LINE(__LINE__), __fb_sp--) \
if(__fb_current__) { \
goto *__fb_current__; \
FIBER_LINE(__LINE__): \
(fb) = __fb_current__; \
__fb_sp--; \
break; \
} \
else
#else
static fiber_t __fb_current__;
static fiber_t __fb_return__;
#define fiber_run(fb) \
__fb_current__ = (fb); \
(fb) = __fb_return__ = &&FIBER_LINE(__LINE__); \
if(__fb_current__) { \
goto *__fb_current__; \
FIBER_LINE(__LINE__): \
(fb) = __fb_current__; \
} \
else
#endif
#define yield() \
do { \
__fb_current__ = &&FIBER_LINE(__LINE__); \
goto *__fb_return__; \
FIBER_LINE(__LINE__): \
; \
} while(0);
#define wait_until(cond) \
while(!(cond)) { \
yield(); \
}
#define fiber_init(fb) \
do { \
(fb) = FIBER_INIT; \
} while (0)
#endif
#include <stdio.h>
#include "fiber.h"
fiber_t fb0 = FIBER_INIT;
fiber_t fb1 = FIBER_INIT;
fiber_t fb2 = FIBER_INIT;
fiber_t fb3 = FIBER_INIT;
fiber_t fb4 = FIBER_INIT;
fiber_t fb5 = FIBER_INIT;
fiber_t fb6 = FIBER_INIT;
int main(int argc, char *argv[])
{
int c = 0;
do {
fiber_run(fb0) {
printf("fiber test\n");
}
fiber_run(fb1) {
printf("%c\n", c + '0');
yield();
}
fiber_run(fb2) {
yield();
printf(" %c\n", c+'0');
}
fiber_run(fb3) {
yield();
printf(" %c\n", c+'0');
yield();
printf(" %c\n", c+'0');
yield();
}
fiber_run(fb4) {
do {
printf(" %c\n", c+'0');
yield();
} while(c < 5);
}
#if FIBER_NEST_ENABLE
fiber_run(fb5) {
do {
yield();
printf(" %c\n", c+'0');
fiber_run(fb6) {
wait_until(c == 9);
printf(" %c\n", c+'0');
}
} while(1);
}
#else
fiber_run(fb5) {
do {
yield();
printf(" %c\n", c+'0');
} while(c < 5);
}
fiber_run(fb6) {
wait_until(c == 9);
printf(" %c\n", c+'0');
}
#endif
} while(c++ < 10);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment