#CommunicatingSequentialProcesses

Karsten Schmidttoxi@mastodon.thi.ng
2024-04-28

Been busy adding more docs & examples/snippets for the revamped thi.ng/csp package, the readme and core operators. Still more to come, but the most important parts & operations are covered now. Please gimme a shout if anything is unclear... I'm aware #CommunicatingSequentialProcesses is yet another fringe technique for many JS/TS devs, but that shouldn't make it any less interesting or elegant, especially these days where async features are fully supported everywhere and there's so much more than ye basic async/await patterns...

(The attached ping-pong example is taken from the updated readme, but barely scratches the surface of what's possible...)

#ThingUmbrella #CSP #CommunicatingSequentialProcesses #Async #OpenSource #Documentation #TypeScript #JavaScript

TypeScript source code of a simple CSP-based communication between 2 async concurrent processes. See package readme (link in toot) for the full source....
Karsten Schmidttoxi@mastodon.thi.ng
2023-08-09

After some friendly inquiry by @computersandblues, I spent a few hours today adding basic CSP (#CommunicatingSequentialProcesses) primitives for thi.ng/fibers and writing some preliminary documentation. I'm amazed how simple (and easy!) it was this time around (compared to thi.ng/csp) and it's giving me big hopes for the fiber based approach in general...

Readme section:
github.com/thi-ng/umbrella/blo

2-channel ping/pong example:
github.com/thi-ng/umbrella/blo

Source code & doc strings:
github.com/thi-ng/umbrella/blo

#ThingUmbrella #TypeScript #Coroutines #CSP #CooperativeMultitasking

Excerpt from readme:

"CSP primitives (Communicating Sequential Processes)

In addition to the operators above, the basic fiber implementation can also be used to construct other types of primitives, like these required for channel-based communication between processes. The package includes a fiber-based read/write channel primitive which can be customized with different buffer behaviors to control blocking behaviors and backpressure handling (aka attempting to write faster to a channel than values are being read, essentially a memory management issue).
Buffering behaviors

The following channel buffer types are included, all accepting a max. capacity and all implementing the required IReadWriteBuffer interface:

fifo: First in, first out. Writes to the channel will start blocking once the buffer's capacity is reached, otherwise complete immediately. Likewise, channel reads are non-blocking whilst there're more buffered values available. Reads will only block if the buffer is empty.

lifo: First in, last out. Read/write behavior is mostly the same as with fifo, with the important difference, that (as the name indicates), the last value written will be the first value read (i.e. stack behavior).

sliding: Sliding window buffer. Writes to the channel are never blocking! Once the buffer's capacity is reached, a new write will first expunge the oldest buffered value (similar to LRU cache behavior). Read behavior is the same as for fifo.
..."TypeScript source code (ping/pong example):

import { channel, fiber, wait } from "@thi.ng/fibers";
import { ConsoleLogger } from "@thi.ng/logger";

// create idle main fiber with custom options
const app = fiber(null, {
    id: "main",
    logger: new ConsoleLogger("app"),
    terminate: true,
});

// create CSP channels (w/ default config)
const ping = channel<number>();
const pong = channel<number>();

// attach ping/pong child processes
app.forkAll(
    // ping
    function* () {
        let x: number | undefined;
        while (ping.readable()) {
            // blocking read op
            x = yield* ping.read();
            // check if channel was closed meanwhile
            if (x === undefined) break;
            console.log("PING", x);
            // blocking write op to other channel
            yield* pong.write(x);
            // slowdown
            yield* wait(100);
        }
    },
    // pong (very similar)
    function* () {
        let x: number | undefined;
        while (pong.readable()) {
            x = yield* pong.read();
            if (x === undefined) break;
            console.log("PONG", x);
            yield* ping.write(x + 1);
        }
    },
    // channel managment
    function* () {
        // kickoff ping/pong
        yield* ping.write(0);
        yield* wait(1000);
        // wait for both channels to close
        yield* ping.close();
        yield* pong.close();
    }
);
app.run();

Client Info

Server: https://mastodon.social
Version: 2025.04
Repository: https://github.com/cyevgeniy/lmst