Introduction

This is a library for CSP in JavaScript, built on top of async/await and the asynchronous iterable interface.

What is CSP?

CSP stands for Communicating Sequential Processes, a model to coordinate concurrency that was described by Richard Hoare in a book of the same name from 1978.
CSP is based on two main primitives: processes and channels.

Due to the single-thread nature of JavaScript, the term process does not refer to an OS process.
It alludes to an entity in the code designed to fulfill a specific task, a piece of code that can complete a unit of work independently.

ES2017 took to us async functions, which correspond to the above description. Their execution can be paused thanks to the await keyword, therefore this type of function can be run concurrently faking threads.

CSP says that processes cannot share memory. What if they need to communicate with each other?
In such case channels come into action!

Installation

$ npm install --save @jfet97/csp

Example Usage

Below is a trivial example of usage, that plays on the standard ping-pong example.

const { Channel } = require('@jfet97/csp');
// or...
import { Channel } from '@jfet97/csp';

const timeout = ms => new Promise(resolve => setTimeout(resolve, ms));

const wiff = new Channel();
const waff = new Channel();

const createBall = () => ({ hits: 0, status: '' });

const createBat = async (inbound, outbound) => {
  while (true) {
    const ball = await inbound.take(); // wait for an incoming ball
    ball.hits++;
    ball.status = ball.status === 'wiff!' ? 'waff!' : 'wiff!';
    console.log(`🎾  Ball hit ${ball.hits} time(s), ${ball.status}`);
    await timeout(500); // assume it's going to take a bit to hit the ball
    await outbound.put(ball); // smash the ball back
  }
};

createBat(waff, wiff); // create a bat that will wiff waffs
createBat(wiff, waff); // create a bat that will waff wiffs

waff.put(createBall());

With the following result:

pingpong

Async Iteration Protocol

Channels implement the async iterable interface, so you can transform the following illustrative code:

async function process (inbound, outbound) {
  while (true) {
    const msg = await inbound.take();
    // do stuff with msg
    await outbound.put(res);
  }
};

into a cleaner version, thanks to the powerful for-await-of:

async function process (inbound, outbound) {
  for await(const msg of inbound) {
    // do stuff with msg
    await outbound.put(res);
  }
};

Credits

Thanks to Joe Harlow for his work on this topic. If you are unfamiliar with CSP, I encourage you to see his talk where he describe a simpler version of this library as well.