Portable Coroutine Library (PCL)
前回までのあらすじ: GNU Pth イイ!と思ったけどよく見ると MinGW をサポートしてなかった。
で、数時間の迷走の結果 (CreateFiberは Win95 ダメだとと知ってみたり、 WINE の CreateFiber を見たり、アセンブラ読んでみたり、自分で作ろうとしてスタックが壊れたり) PCL というのを見つけました。
http://xmailserver.org/libpcl.html
ポータブルという割には MacOSX も MinGW も Cygwin もダメだったんですけど、 Io から jmp_buf に esp と eip を保存しているらしいコードをひっこぬいてきたら、 MacOSX でも MinGW でも動くようになりました。 Solaris はダメみたいで、 Cygwin, Zaurus, FreeBSD, NetBSD, VC あたりは動くはず…今度確認します。
これがパッチ。
http://shinh.skr.jp/dat_dir/pcl_ioarch.patch
ちなみに GPL なのが人によっては困りどころかもしれません。 GPL イヤンな人は IoVM の Scheduler.[ch] と Coro.[ch] あたりでなんとかなるかもしれません。
pcl.d
extern (C) { alias void* coroutine_t; coroutine_t co_create(void (*func)(void *), void *data, void *stack, int size); void co_delete(coroutine_t coro); void co_call(coroutine_t coro); void co_resume(); void co_exit_to(coroutine_t coro); void co_exit(); coroutine_t co_current(); }
test_pcl.c
#include#include #define CO_STACK_SIZE (8 * 1024) void spawn1(void* arg) { int i = 0; int fiber = (int)arg; printf("1 %d %d\n", fiber, i+=2); co_resume(); printf("4 %d %d\n", fiber, i+=2); co_resume(); } void spawn2(void* arg) { int fiber = (int)arg; int i = 0; printf("2 %d %d\n", fiber, i++); co_resume(); printf("5 %d %d\n", fiber, i++); co_resume(); } int main() { coroutine_t co1, co2; co1 = co_create(&spawn1, (void*)1, NULL, CO_STACK_SIZE); co2 = co_create(&spawn2, (void*)2, NULL, CO_STACK_SIZE); printf("ok?\n"); co_call(co1); co_call(co2); printf("3\n"); co_call(co1); co_call(co2); co_delete(co1); co_delete(co2); }