Theasync / awaitidiom is becoming increasingly popular. The first widely used language to include it was C #, and it has now spread into JavaScript and Rust. Now C / C programmers don’t have to feel left out, becauseasync.his a header-only library that brings async / await to C!
Features:
- It’s 100 % portable C.
- It requires very little state (2 bytes).
- It’s not dependent on an OS.
- It’s a bit simpler to understand than protothreads because the async state is caller-saved rather than callee-saved.
# include "async.h" struct async pt; struct timer timer; async example (struct async * pt) { async_begin (pt); while (1) { if (initiate_io ()) { timer_start (& timer); await (io_completed () || timer_expired (& timer)); read_data (); } } async_end; }
This library is basically a modified version of the idioms found in theProtothreadslibrary by Adam Dunkels, so it’s not truly ground breaking. I’ve made a few tweaks that make it more understandable and generate more compact code, and I also think it more cleanly maps to the async / await semantics than it does to true threading.
Protothreads and async.h are both based around local continuations, but where protothreads are callee-saved, async.h is caller-saved. This eliminates the need to pass in the local continuation to any async operations exceptasync_begin
. This simplifies the macros that implement the async / await idiom, and even simplifies code that uses async.h.
Here’s a simple example of fork-join style “parallelism”:
# include "async.h" typedef struct { async_state; struct async nested1; struct async nested2; } example_state; example_state pt; async nested (struct async * pt) { async_begin (pt); ... async_end; } async example (example_state * pt) { async_begin (pt); // fork two nested async subroutines and wait until both complete async_init (& pt->nested1); async_init (& pt->nested2); await (async_call (nested, & pt->nested1) & async_call (nested, & pt->nested2)); // fork two nested async subroutines and wait until at least one completes async_init (& pt->nested1); async_init (& pt->nested2); await (async_call (nested, & pt->nested1) | async_call (nested, & pt->nested2)); async_end; }
GIPHY App Key not set. Please check settings