Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # A Study on Coroutines in plain C
- This approach provides a very simple implementation of asymmetric coroutines.
- Unfortunately, unlike Python's Generators, this solution has no means of state preservation.
- The only thing one can do with these coroutines is iterate through them until full exhaustion or until manual halt.
- ### How to Use it
- One defines coroutines almost as regular C routines, yet with `coroutine` keyword.
- Defined coroutines can later be invoked with `take` construct.
- Apart from being a regular routine, a coroutine can, within its body,
- either `yield` to provide the consumer with one generated value,
- or `return` to immediately cease execution thus producing no further values.
- Each time a coroutine `yield`s, the control flow passes to consumer party to `take` statement
- with its iterator set to just `yield`ed value.
- Within its body, `take` has the pre-declared iterator,
- and two additional keywords: `next` and `stop`.
- These keywords are used to decide whether the execution
- of iterated coroutine should continue.
- Each control branch of a `take` body should always end with either `next` or `stop`.
- ### Symbols
- `coroutine.h` module introduces five keywords.
- * `coroutine` declares a new one.
- The first argument is return type of the declared coroutine, and the second argument is its name.
- This order is taken from C routine declaration: instead of `int fib()` one would write `coroutine(int, fib)`.
- Naturally, since these coroutines cannot keep their state, there is no need in input arguments to them.
- * `take` consumes a coroutine's yield.
- First argument is iterator type, has to be the same as return type of the coroutine being consumed.
- Second argument is the name of iterator. Third argument is the name of a previously defined coroutine.
- Fourth argument is the loop body, which would have access to the iterator as defined with first and second argument.
- Mnemonic: `take [int] each in <coro> with <this body>`.
- * `yield` is used in coroutine body to set the iterator value.
- * `next` is used in consumer body to claim more values from iterated coroutine if there are any.
- * `stop` is used in consumer body to interrupt the execution flow of the iterated coroutine.
- If `stop`ped, the last `yield` behaves like `return`.
- ### Platform
- This works on Clang and GCC.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement