Article View: pl.comp.lang.c
Article #310065Coroutines w (GNU) C
From: Maciek Godek
Date: Fri, 24 Jan 2020 11:44
Date: Fri, 24 Jan 2020 11:44
65 lines
3426 bytes
3426 bytes
Jeśli by to kogoś interesowało, to dziś "wymyśliłem" prosty sposób na implementację "coroutines" w C.
Pomysł opiera się na rozszerzeniu kompilatora GCC pozwalającym na przechowywanie etykiet dla goto w zmiennych, i możliwości skakania do tych zmiennych:
https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
Interfejs jest taki, że na początku funkcji musimy wywołać makro
COROUTINE_START()
i dalej możemy użyć
COROUTINE_RETURN(wartość)
co zadziała jak normalne wyjście z funkcji, albo
COROUTINE_YIELD(wartość)
co spowoduje przerwanie egzekucji funkcji, przy czym kolejne wywołanie
funkcji spowoduje jej kontynuowanie za ostatnio wykonanym wyrażeniem COROUTINE_YIELD.
Na przykład kod może wyglądać tak:
int coroutine() {
COROUTINE_START();
printf("started\n");
COROUTINE_YIELD(1);
printf("stage 1\n");
COROUTINE_YIELD(2);
printf("stage 2"\n");
COROUTINE_YIELD(3);
printf("finishing\n");
COROUTINE_RETURN(4);
}
Drobny problem jest z przekazywaniem parametrów: jeżeli chcemy, żeby wartości argumentów były przechowywane między wywołaniami, to musimy je zapisywać w zmiennych statycznych.
Implementacja składa się z nieco ponad 20 linii kodu:
#define COROUTINE_START() \
static void *coroutine_continuation = \
&&coroutine_start; \
goto *coroutine_continuation; \
coroutine_start: \
do {} while(0)
#define COROUTINE_RESTART \
coroutine_continuation = &&coroutine_start
#define COROUTINE_RETURN(...) \
COROUTINE_RESTART; return __VA_ARGS__
#define _COROUTINE_LABEL(line) coroutine_##line
#define COROUTINE_LABEL(line) _COROUTINE_LABEL(line)
#define COROUTINE_YIELD(...) \
coroutine_continuation = \
&&COROUTINE_LABEL(__LINE__); \
return __VA_ARGS__; \
COROUTINE_LABEL(__LINE__): \
do {} while(0)
Technical Details
Message-ID:
<4375b52d-ba21-462a-8844-9bd1a02e9ece@googlegroups.com>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!news-2.dfn.de!news.dfn.de!2.eu.feeder.erje.net!3.eu.feeder.erje.net!feeder.erje.net!weretis.net!feeder7.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!g89no5870741qtd.0!news-out.google.com!w29ni238qtc.0!nntp.google.com!g89no5870736qtd.0!postnews.google.com!google-groups.googlegroups.com!not-for-mailShow Full Headers
Complete Article Headers
X-Received: by 2002:a05:6214:1634:: with SMTP id e20mr2266451qvw.205.1579866254837; Fri, 24 Jan 2020 03:44:14 -0800 (PST) X-Received: by 2002:a25:afd1:: with SMTP id d17mr1953953ybj.92.1579866254621; Fri, 24 Jan 2020 03:44:14 -0800 (PST) Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!news-2.dfn.de!news.dfn.de!2.eu.feeder.erje.net!3.eu.feeder.erje.net!feeder.erje.net!weretis.net!feeder7.news.weretis.net!proxad.net!feeder1-2.proxad.net!209.85.160.216.MISMATCH!g89no5870741qtd.0!news-out.google.com!w29ni238qtc.0!nntp.google.com!g89no5870736qtd.0!postnews.google.com!google-groups.googlegroups.com!not-for-mail Newsgroups: pl.comp.lang.c Date: Fri, 24 Jan 2020 03:44:14 -0800 (PST) Complaints-To: groups-abuse@google.com Injection-Info: google-groups.googlegroups.com; posting-host=213.192.68.153; posting-account=f7iIKQoAAAAkDKpUafc-4IXhmRAzdB5r NNTP-Posting-Host: 213.192.68.153 User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <4375b52d-ba21-462a-8844-9bd1a02e9ece@googlegroups.com> Subject: Coroutines w (GNU) C From: Maciek Godek <godek.maciek@gmail.com> Injection-Date: Fri, 24 Jan 2020 11:44:14 +0000 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit