Lely core libraries 2.3.4
|
This header file is part of the utilities libraru; it contains a stackless coroutine implementation. More...
Go to the source code of this file.
Data Structures | |
struct | co_ctx_t |
The type holding the context (i.e., program counter) of a stackless coroutine. More... | |
Macros | |
#define | CO_LABEL_TYPE int |
The type used to store the label (i.e., program counter) of a stackless coroutine. More... | |
#define | CO_CTX_INIT |
The static initializer for co_ctx_t. | |
#define | co_restart(ctx) co_restart__(ctx) |
Resets a stackless coroutine so the next invocation starts at the beginning. | |
#define | co_is_ready(ctx) co_is_ready__(ctx) |
Returns 1 if the stackless coroutine has finished. | |
#define | co_reenter(ctx) co_reenter__(ctx) |
Defines the body of a stackless coroutine. More... | |
#define | co_yield co_yield__(co_label__) |
Stores the context of the current stackless coroutine, evaluates the expression following the co_yield keyword, if any, and exits the scope of the co_reenter statement. More... | |
#define | co_fork co_fork__(co_label__) |
"Forks" a coroutine and executes the expression following the co_fork keyword as a child (i.e., co_is_child() returns 1). More... | |
#define | co_is_parent() (!co_is_child()) |
Returns 1 if the calling stackless coroutine is the parent of a fork. | |
#define | co_is_child() (*_co_label_ < -1) |
Returns 1 if the calling stackless coroutine is the child of a fork. | |
This header file is part of the utilities libraru; it contains a stackless coroutine implementation.
The implementation is pure and compliant C99 and does not require any part of the standard library. It is an adaptation of the C++ stackless coroutine from Boost.Asio by Christopher M. Kohlhoff. This is itself a variant of Simon Tatham's Coroutines in C, which was inspired by Duff's device.
The implementation (ab)uses the switch statement. It is therefore not possible to yield from a coroutine from within a nested switch statement.
Since the implementation is stackless, variables local to the coroutine are not stored between invocations. In C++, this drawback can be partially mitigated by implementing the coroutine as a function object and making all local variables (private) data members.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Definition in file coroutine.h.
#define CO_LABEL_TYPE int |
The type used to store the label (i.e., program counter) of a stackless coroutine.
A smaller type may be used in constrained environments, especially if the __COUNTER__
macro is available.
Definition at line 46 of file coroutine.h.
#define co_reenter | ( | ctx | ) | co_reenter__(ctx) |
Defines the body of a stackless coroutine.
When the body is executed at runtime, control jumps to the location immediately following the last co_yield or co_fork statement.
Note that a function MUST NOT contain multiple co_reenter
expressions with the same context.
Definition at line 110 of file coroutine.h.
#define co_yield co_yield__(co_label__) |
Stores the context of the current stackless coroutine, evaluates the expression following the co_yield
keyword, if any, and exits the scope of the co_reenter statement.
co_yield break
terminates the coroutine (i.e., after this statement, co_is_ready() returns 1). co_yield continue
is equivalent to co_yield
.
A co_yield
expression is valid only within a co_reenter statement. Since co_reenter is implemented using a switch
statement, co_yield
CANNOT be used from within a nested switch
statement.
Definition at line 143 of file coroutine.h.
#define co_fork co_fork__(co_label__) |
"Forks" a coroutine and executes the expression following the co_fork
keyword as a child (i.e., co_is_child() returns 1).
This expression will typically create a copy of the coroutine context. After the expression completes, the coroutine continues and co_is_parent() returns 1. If the coroutine is reentered with (the copy of) the context created by co_fork
, co_is_child() returns 1 until the next co_yield
statement.
For example:
This works especially well with function objects in C++. The canonical use case is a server accepting and handling connections:
Definition at line 220 of file coroutine.h.