.. SPDX-License-Identifier: GPL-2.0 or GPL-3.0 .. Copyright © 2018-2019 Ariadne Devos
Tasks are things that might need to do potentially-blocking IO (e.g. recv(2), send(2) or accept(2)) or may take a non-negligible amount of time (e.g. compilation or factoring semiprimes).
The former should non-blocking, and the latter time-sliced. This is implemented with a kqueue (*BSD) or epoll instance (Linux), an event loop, cooperative multitasking, and recursion, sort of.
(There is no intention to port this to Windoze as long as it doesn't have a synchronous edge-polled event-notificaton mechanism.)
The entity that actually performs tasks is the worker.
Tasks of the same type are batched to reduce pressure on the caches. (As a side-effect, there are only a limited number of indirect calls.) Each task type has its own worker, which are a task of their own, of the top-level worker. (These two types of workers are implemented differently.)
This creates three levels of tasks: the top-level worker, type-specific task sets and tasks.
A worker should not block waiting for IO readyness if there are tasks, possibly of different workers, that may continue even if there is no change in IO readyness. In that case, it should rather poll.
To avoid blocking in this case, but without busy-waiting, a worker only blocks if no workers have pending tasks.
E.g., there is a type for sockets (), tasks () homogeneous workers (task sets) (), heterogeneous workers () and listening sockets ().
A HTTP proxy connection task type may be composed of single sHT_task and two sHT_task. If a callback's argument is a pointer to an sHT_task, a pointer to the embedding structure can be calculated by sHT_container_of ().
TODO Allow multiple streams within a task.
A worker has some structures for using the kernel's readyness notification mechanism and a queue of tasks to do.
It is assumed that the number of tasks in a heterogeneous worker is epsilon, such that we can do a simple loop over all tasks and always perform them (to avoid all indirect calls and provide a stable ordering).
When a task is performed, it is passed the worker it is in. (Although it is not disallowed, there is no explicit support for tasks being in multiple workers at the same time.)
TODO