This project is part of the @thi.ng/umbrella monorepo.
Process hierarchies & operators for cooperative multitasking.
This package provides a
Fiber
primitive
acting as wrapper around ES6 generators (co-routines) and supplements them with
nested child processes, cancellation, error & event handling and (optional)
logging features. Additionally, there're a number of fiber-related utilities and
higher order operators to construct and compose fibers.
import { fiber, wait } from "@thi.ng/fibers";
import { ConsoleLogger } from "@thi.ng/logger";
// wrap an endless generator as fiber
const app = fiber(
function* () {
while(true) {
console.log("hello");
// wait 0.25s
yield* wait(250);
console.log("fiber");
// wait 1s
yield* wait(1000);
}
}
);
// start processing it with default handlers
// see: https://docs.thi.ng/umbrella/fibers/classes/Fiber.html#run
app.run();
// create a child process which runs semi-independently
// (only executes if parent is still active)
// child fibers are auto-removed from parent when they terminate
const child = app.fork(
// the `ctx` arg is the fiber wrapping this generator
function* (ctx) {
for(let i = 0; i < 3; i++) {
ctx.logger?.debug("count", i);
yield* wait(100);
}
// return value will be stored in fiber for future reference
return 42;
},
// fiber options
{
// custom fiber ID (else autogenerated)
id: "child-demo",
// custom logger (default: none)
logger: new ConsoleLogger("child")
}
);
// hello
// [DEBUG] child: init child-demo
// [DEBUG] child: count 0
// [DEBUG] child: count 1
// [DEBUG] child: count 2
// fiber
// [DEBUG] child: done child-demo 42
// [DEBUG] child: deinit child-demo
// hello
// fiber
// hello
// ...
// once a fiber has completed, its value can be obtained
// e.g. here we create another fiber, which first waits for `child` to complete
app.fork(function* () {
// wait for other fiber
const result = yield* child;
console.log("result", result);
// alt way to obtain value
console.log("deref", child.deref());
});
// result 42
// deref 42
The following operators act as basic composition helpers to construct more elaborate fiber setups:
all
: wait for all given fibers to completefirst
: wait for one of the given fibers to completefork
: create & attach a new child processforkAll
: create & attach multiple child processesjoin
: wait for all child processes to completesequence
: execute fibers in sequencetimeSlice
: execute fiber in batches of N millisecondsuntil
: wait until predicate is truthyuntilEvent
: wait until event occursuntilPromise
: wait until promise resolves/rejectsuntilState
: stateful version ofuntil
wait
: wait for N milliseconds or indefinitelywaitFrames
: wait for N frames/tickswithTimeout
: wait for given fiber, but only max N milliseconds
The @thi.ng/transducers package can be very helpful to create complex fiber setups, for example:
import { sequence, wait, type MaybeFiber } from "@thi.ng/fibers";
import {
cycle,
interpose,
map,
partition,
repeatedly,
} from "@thi.ng/transducers";
const defWorkItem = (id: number) =>
function* () {
console.log("part", id);
};
const defWorkGroup = (items: MaybeFiber[]) =>
function* () {
// interject a short pause between given work items
// then execute in order and wait until all done
yield* sequence(interpose(() => wait(100), items));
console.log("---");
yield* wait(1000);
};
// create fiber which executes given sub-processes in order
sequence(
// generate 25 work items
// partition into groups of 5
// transform into iterable of work groups
// repeat indefinitely
cycle(map(defWorkGroup, partition(5, repeatedly(defWorkItem, 25))))
).run();
// part 0
// part 1
// part 2
// part 3
// part 4
// ---
// part 5
// part 6
// part 7
ALPHA - bleeding edge / work-in-progress
Search or submit any issues for this package
yarn add @thi.ng/fibers
ES module import:
<script type="module" src="https://cdn.skypack.dev/@thi.ng/fibers"></script>
For Node.js REPL:
const fibers = await import("@thi.ng/fibers");
Package sizes (brotli'd, pre-treeshake): ESM: 1.88 KB
Several demos in this repo's /examples directory are using this package.
A selection:
Screenshot | Description | Live demo | Source |
---|---|---|---|
Fiber-based cooperative multitasking basics | Demo | Source |
TODO
If this project contributes to an academic publication, please cite it as:
@misc{thing-fibers,
title = "@thi.ng/fibers",
author = "Karsten Schmidt",
note = "https://thi.ng/fibers",
year = 2023
}
© 2023 Karsten Schmidt // Apache License 2.0