Contents
This page is in group Technology
Intro
There are some implicit Wiki-refs at the bottom. These terms are be bold at first occasion.
I want learn a little more on CSP (Communicating Sequential Processes), and from zero I want to learn about Node.js, Clojure, ClojureScript (all server side) and JavaScript (client side).
I will learn by reading, writing and discussing how David Nolen [01] and Ola Holmström [02] have solved «Go-type concurrency» in ClojureScript and Node.js. And also read about the Clojure core.async Channel initiative [11].»
I don’t guarantee that this will ever be finished, as the web technology in scope is far from my traditional embedded background. But then, it’s at work that I already see all the technologies in use – but not in combination with CSP.
The late missing context
When I read this note after a couple of years (in 2016) I saw it missing some context. Here’s a try (scrambled from Wikipedia and my needs here):
JavaScript code often uses Node.js runtime so that it can run on several platforms. Clojure is a completely different Lisp-type language that runs on Java Virtual Machine (JVM) and (by help of ClojureScript) also to ClojureCLR, Common Language Runtime, and JavaScript engines. Core.async is a CSP-type library for Clojure, both developed by Rich Hickey. So, JavaScript has nothing to do with core.async, but core.async can run in a JavaScript environment
Now, did I get that about right?
«These days, new languages sit on top of the old virtual machines. Clojure, Scala, Jython, JRuby — they’re all piggybacking off Sun’s (now part of Oracle) great work in building the VM.» [16].
Ponderings
You will find several blog notes where I have tried to find the rationale for process model by registering callbacks in a single-threaded and consequenctly non-blocking environment. You will find them in my list of technology notes (also covering newer notes, of course), but I guess this issue has been developed starting with (072) Pike & Sutter: Concurrency vs. Concurrency then (075) Eventual concurrency, (077) A reactive manifest and (078) HTML5 and concurrency. (Later I have written the (114) JavaScript tree becoming concurrent?)
Update 3Apr2020: I guess one of the best references here is [21] where the author of the Erlang programming language writes about «Red and Green callbacks«. I suggest you read it before proceeding here.
In the blog notes I have tried to argue that the mentioned and overpraised process model is not the only possible. The alternative is f.ex. CSP-type (light-weight) processes, fully encapsulated with only communication as side effects, where local reasoning is the rule. But I have thought that this was mostly for the embedded world, not so much for streaming-type web-applications. Even if much of the formal analysis in the CSP textbooks is about buffering. But then Martin at work pointed my to these CSP GitHub pages (thanks!). In addition I think I will look at CSP for Python – PyCSP as well [03] (plus separate chapter here). Three rather interesting ways to look at CSP.
But what kind of applications will these three CSP solutions typically be used for? I will have to delve into them and study the examples.
Motivation
Thinking it over, the heading of this note should have included PyCSP. It has been in development since 2006 and the newest update is from 2013, a year ago. It looks rather complete, and has been developed by people in the «CSP community».
Nolen’s ClojureScript code is newer. His examples at GitHub look very interesting. And his three blog notes there are also interesting reading, indeed.
Holström’s node-csp is packed as a Node.js library. He explicitly says he’s been inspired by Nolen. In a private mail he says that he did this «hobby project» with the intention to use Nolen’s ideas and challenge to implement a select (such a selective choice is not the same as a switch/case).
I left a trace on GitHub about this blog note: https://github.com/Aclassifier/This-and-their-CSP – «Studying Communicating Sequential Processes on top of basically single-threaded asynchronous non-blocking and therefore callback based systems.»
A related story: I did build CSP on top of an asynchronous run-time system myself. From what I have observed none of the three systems I am discussing here got into the same trouble as I did with the SDL to CSP «impedance mismatch». See [04].
Quotes
Clojure concurrency
(This chapter precludes the next chapter on core.async.) Since ClojureScript is «a subset of Clojure, compiled to optimized JavaScript, intended for use in web browsers and mobile devices» (Wiki-ref below) I wanted to look at Clojure. There is an interesting document on this by Rich Hickey (the designer of Clojure – and core.async) at [10]. I started by reading myself up, but then I was left with more questions than answers, so I decided to become a member of the Clojure forum and start by asking some questions there (26Oct2014: stay tuned). Here’s the thread, it’s become very interesting! Among several matters I asked this question:
Is it correct to say that never to block means never to be 100% sure that a transaction succeeds at first attempt? Answer: «Yes»
This chapter flows directly into the next chapter:
core.async channels library
The description of the core.async channels library [11] was pointed to me by Leon Grapenthin at the Clojure discussion group (thanks!). First, here’s the basic basics of Clojure:
Clojure’s focus on programming with immutable values and explicit progression-of-time constructs are intended to facilitate the development of more robust programs, particularly multithreaded ones. … Concurrent programming through software transactional memory, an agent system, and a dynamic var system. (Wikipedia, 2014)
An interesting point to keep in mind: when a synchronous CSP-type channel sends from one process to another the process that arrives first on the channel has to wait and consequently yield down to the scheduler; until the second part arrives (there are two in this case); then data is moved; after which both parties are free. If the sender were first on the channel then the value to be sent is made «immutable»; if the receiver were first then the space to fill data to is «protected». When it’s finished the restrictions are «lifted». It’s a kind of «channel implicit immutability»!?
core.async is a library based on previous CSP work (it even acknowledges this) wrapped into standard Clojure, in need of no extra run-time (so it runs on top of missing support of threads and queues on the JavaScript engine). It’s meant to be an alternative to java.util.concurrent. «Callback hell» is described and used as a rationale for using channels and concurrency, as is the «unenthusiasm» of actors. (Remember everything that runs in code on a single core really runs sequentially: so every concurrent description also would have a sequential form). From the document by Rich Hickey:
The objectives of core.async are:
- To provide facilities for independent threads of activity, communicating via queue-like channels
- To support both real threads and shared use of thread pools (in any combination), as well as ClojureScript on JS engines
- To build upon the work done on CSP and its derivatives
It is our hope that async channels will greatly simplify efficient server-side Clojure programs, and offer simpler and more robust techniques for front- end programming in ClojureScript.
The library supports channel sending (put) and receiving (take) with blocking and non-blocking versions. Even if Clojure has both >!! and <!! (that block the main thread) and >! and <! (which do not) I am not sure how that maps into the blocking I describe in another blog note, referenced below. But I guess this example gives some of the answer: (thread (>!! c "hello")) will spawn an extra thread to avoid the main thread to block the others [14]. Quote from the same reference (precluding some from below): «The go macro asynchronously executes its body in a special pool of threads. Channel operations that would block will pause execution instead, blocking no threads. This mechanism encapsulates the inversion of control that is external in event/callback systems.» There also is selective choice (alt) – in blocking and non-blocking versions, prioritised and nondeterministic (the non-blocking has a default clause (TRUE & SKIP in occam’s ALT) that’s taken if no channel s immediately available («if no guard is ready» in CSP wording). Channels may be «multiple writers and readers. By default, the channel is unbuffered, but you can supply a number to indicate a buffer size, or supply a buffer object created via buffer, dropping-buffer or sliding-buffer.» Buffer size is not like the length of a pipe (in bytes, untyped) but max number of messages (=typed). Timers are also channels, with the «sender» end being the timer system.
Another matter: with non-blocking versions of the above one turns applications into busy pollers. It should probably be used only when really necessary.
The mechanism to enable to run the application code is the go macro that is expanded at compile time. The go macro is a lightweight process. JavaScript is able to run (1) «inversion of control» (=IOC, see wiki-refs below – new term to me: thread relinquishing, thread pools, callbacks, event handlers) or better indirectly (2) these go blocks. The Clojure expanded go macro contains synchronisation points. The compiler has flattened out the state space and channel communication to sequential IOC-style Clojure code. But the IOC is like assembly code, it’s the Clojure CSP stuff that’s user code. (I guess this flattening out might(?) be compared to the SPoC (occam to C) compiler that did something similar when it flattened nested occam non-concurrent PROCs with channel usage into concurrent PROCS ready to be scheduled like the concurrent PROCS (I have written about this, see here)).
Leon Grapenthin writes in a private mail to me some facts that are easy to oversee:
core.async is implemented platform dependent on the JVM and JS (and possibly CLR). The API is the same however, except for the lack of thread blocking operations on JS: core.async on the JVM supports two kinds of all blocking operations: thread blocking and go-blocking where the latter «blocks» within a go block. The ClojureScript version, due to a lack of threads, only allows the latter one.
The question and my answer here clojure-why-does-execution-hang-when-doing-blocking-insert-into-channel could be interesting to you, as well.
Even if not everything runs on everything…
…please spend 45 minutes listening to Rich Hickey’s lecture [12]. It’s a pedagogical masterpiece when he comes to the final part outlining the difference between callback / event loops and channels / ALTs / processes. He does not hide what he thinks. After that, if you’d like an interview there’s one with Timothy Baldridge’s on the go macro [15]. Both Rich and Timothy seem to work at Cognitect (at Durham, North Carolina, USA)
Also, there are implementation details described (of Clojure on Java), with questions and answers (generally about channels and alts etc.) at [13]. The go macro has several thousand lines of code; and this is not built on generators (see below).
However, I am somewhat unenthusiastic about the «async» name. Channels are default «blocking» (if you want to read about what blocking is and is not I have as mentioned written about it at Not so blocking after all – where you will also find Rich Hickey’s wording about park or parking calls instead of blocking). But async sells better! Maybe Hickey is referring to the connecting, asynchronous sending side of channels that pick up callbacks. That’s where most of us are. But then, that’s where he’s helping us move away from. (Hem, did I get that right?)
Nolen
Some quotes from Nolen’s «Communicating Sequential Processes» (I did the underlining):
With the arrival of core.async, ClojureScript provides a powerful advantage over other popular compile to JavaScript languages.
JavaScript promises don’t solve the inversion of control problem – callback hell is unnested but it’s still callback hell.
It’s important to understand that go blocks paired with loop/recur allow us to create local event loops. Normally when writing client side code you are participating in a global event loop. As with global mutable variables, global event loops defy local reasoning.
When reading from a channel alts! will return a tuple, the first element is the value read from the channel and the second element is the channel that was read from.
Note this is quite different from the usual JavaScript solutions where we tend to smear our asynchronous handling across the code base
Some quotes from Nolen’s «CSP is Responsive Design»:
I believe there are three main elements not called Model View Controller (MVC) (nor any other arbitrary variation on that tired old theme). The trichotomic design I’d like to suggest is more fundamental:
1. Event stream processing
2. Event stream coordination
3. Interface representation
It is interesting that he’s distancing himself away from the MVC. I have tried to learn about MVC in this blog note.
PyCSP etc.
PyCSP update 20Sep2021
The «official» version has been labeled as «discontinued». Any sporadic work is done in https://github.com/PyCSP or https://pycsp.github.io/ – in other work, a continuation of [19]. Source: private mail with John Bjørndalen.
And here are PyCSP’s virtues:
- A flexible CSP library for Python
- Synchronous communication
- Buffered channels
- Multiple process types such as, greenlets, threads, processes and remote processes
- Both input and output guards supported in external choice (Alts)
- A single any-to-any channel type
- Mobile channel-ends
- Retire and poison signals for shutting down networks nicely
- A channel which can communicate using inter-process communication as well as sockets.
- A PyCSP providing local and distributed communication using only standard python modules bundled with CPython
- NAT traversal
- Tracing PyCSP executions to a log file, for later visualisation
Another interesting CSP library I have discovered is Twisted-CSP [07]. Twisted is an event-driven (callback based) library for Python, supporting probably all you need of internet protocols. But even then, Space Monkey has dumped it:
But then, here’s a blog about dumping Python for Go, written by a developer at Space Monkey. Read his very interesting blog at [08]. That blog is also interesting in the light of the themes in some of my own blog notes.
aPyCSP – Asynchronous PyCSP
Update 22Aug2018: aPyCSP is using coroutines and Python asyncio [20].
At CPA 2018 in Dresden Dr. Bjørndalen et al list that generators are «functions returning new values on demand» and «continuing executions from the yielding instructions» and that «Python generators can receive values when reactivated». From the presentation of [19]. The Abstract states that «This paper explores two implementation approaches for aPyCSP where the most recent version is shorter, simpler to read and understand and supports more functionality than the original version, including generic channel support and input and output guards.»
Matters
Holmström and node-csp
The JavaScript code, examples and explanation are dense and with little comments for a starter like me. But they are interesting. I plan to use some of this in a forthcoming lecture for embedded.TRD. Even if I assume that the yield statements in the examples really tell me that JavaScript is not a concurrent language (but yielding must yield something for something else… (like a lightweight thread?)), these yields may constitute an educational tool:
How to twist the brain from thinking single-threaded to thinking multi-threaded: Repeat after me:
Run the code «here» until it blocks (cannot proceed); if the blocking (even of an invisible code down a call-tree) appears and it has an enclosing yield (somewhere up the tree), then instead simply do another function that’s ready! This «then do another function» tells that a scheduler (of some sort) works and that blocking is not evil. When the set-aside function’s blocking condition is later removed (by another function like a «sender», «receiver» or a «timeout»), then the first function will become ready to run. Of course, it wouldn’t had blocked on itself; that’s a deadlock. The possibility of a deadlock does does not rule out blocking, just like the possibility of a stack overflow does not rule out recursion or heap overflow does not rule out dynamic objects or division by zero does not rule out division or.. All these matters are ruled out by design.
This is like the explicit transfer of control (with TRANSFER and IOTRANSFER) that we used here at work in the BS-100 fire panel the eighties with Modula-2’s coroutines. After that I worked with occam for some years, which has process as a first class citizen of the language, and yield is not needed. Like now with Go.
All this being said, the JavaScript formal semantics of yield is part of the semantics of generators as defined in ECMAScript 6 (ES6) [05]. Nolen tells this in [01]. I have a long way to go on this! Again 2: Clojure core.async is not built on generators.
(I tried to write something about this at golang-nuts: «Blocking threads to serve connections faster than non-blocking threads?», see https://groups.google.com/forum/#!topic/golang-nuts/fjY4B3MgOUE. This is a very interesting thread.)
Here is an excerpt from the JavaScript code perhaps indicating what’s available:
var Chan = exports.Chan = function (size) { Chan.prototype.put = function (msg) { Chan.prototype.take = function () {" var Proc = function (gen) { Proc.prototype.run = function () { if (type === "chan") { if (op.state === "continue") { if (type === "fn") { if (type === "spawn") { if (type === "quit") { Proc.prototype.spin = function () { var spawn = exports.spawn = function () { var select = exports.select = function () { var wait = exports.wait = function (ms) { var wrap = exports.wrap = function (fn) { var chanify = exports.chanify = function (fn) { var quit = exports.quit = function () {
I notice that op.state is set to «sleep» or «continue» but only explicitly tested for «continue», but that’s probably ok since it only takes two values. And type is «chan», «fn», «spawn» and «quit».
He certainly generates a whole scheduler in his run method. No he doesn’t! In a mail to me he states that he relies on the asynchronous mechanisms in Node.js by doing the setImmediate so that the next poll of op.state does not block.
yacol
(20Nov2016) There is an interesting js-csp inspired development here by tomaskulich. It’s called yacol. See https://github.com/olahol/node-csp/issues/1 and his project at https://github.com/vacuumlabs/yacol/. It’s basically about error handling. I’d certainly like to read what Ola Holmström might comment. I imagine, that’s probably what Tomáš Kulich is hoping for too. Personally I did a comment there.
Generators
So ES6 has implemented Generator and then «First-class coroutines, represented as objects encapsulating suspended execution contexts (i.e., function activations). Prior art: Python, Icon, Lua, Scheme, Smalltalk.» [05]. Again 3: Clojure core.async is not built on generators.
In the Wikipedia article about Generator I read:
Generators, also known as semicoroutines.. However, it is still possible to implement coroutines on top of a generator facility, with the aid of a top-level dispatcher routine (a trampoline, essentially) that passes control explicitly to child generators identified by tokens passed back from the generators.. Coroutines are useful to implement the following: (…) Communicating sequential processes where each sub-process is a coroutine. Channel inputs/outputs and blocking operations yield coroutines and a scheduler unblocks them on completion events
This is what Nolen describes more in his «ES6 Generators Deliver Go Style Concurrency». Ola Holmström sent me the Mozilla Developer Network’s Generator page, see [06].
Update 8May2017, this time refs to Python: In [17] (What does the “yield” keyword do in Python?) there is a nice description of yield, showing that in the time frame as being used as iterator, each element to iterate over is returned, in the generator, by a yield in it, once and only once. There’s no history or future, there is only the present value allocating memory. In my world I would think of it as a channel delivering the next value to iterate over, delivered by a generator process. In this respect I also learn that searching trees may be done with generators, not having to allocate the whole tree first [18] (Python generators).
Chrome 39 Beta
A continuation of the above chapter about generators: In Oct2014 Google states in their Chrome 39 release note [09] that:
Writing asynchronous code in JavaScript can be less than straightforward. It often involves several nested functions and non-linear program execution, making it hard to develop, maintain and debug. This is such a common pain point for developers that they’ve given it a name: callback soup.
Starting today, Chrome Beta supports ES6 Generators. They allow developers to create iterators that pause their execution after yielding a value, and resume again when later invoked. This greatly simplifies the process of developing asynchronous code and reduces dependence on callback functions.
This so much points ahead. Also, the rationale, almost a confession.
References
Wiki-refs: ClojureScript (routes to Clojure), Coroutine, CSP, Generator, GitHub, Inversion of control (IOC), JavaScript, NAT traversal, Modula-2, Node.js, Python, Twisted event-driven library for Python
- David Nolen («swannodette») at https://github.com/swannodette.
From http://swannodette.github.io/:
Communicating Sequential Processes
http://swannodette.github.io/2013/07/12/communicating-sequential-processes/
CSP is Responsive Design
http://swannodette.github.io/2013/07/31/extracting-processes/
ES6 Generators Deliver Go Style Concurrency, (ES6 = ECMAscript 6), see
http://swannodette.github.io/2013/08/24/es6-generators-and-csp/ - Ola Holmström («olahol», home page at https://www.npmjs.org/~olahol) at https://github.com/olahol
node-csp
https://github.com/olahol/node-csp (explanation: https://www.npmjs.org/package/csp) - PyCSP, see https://code.google.com/p/pycsp/ (9.2021 broken link, see PyCSP update 20Sep2021)
- Øyvind Teig, «A scheduler is not as transparent as I thought», see http://www.teigfam.net/oyvind/pub/notes/18_A_scheduler_is_not_so_transparent.html
- [[harmony:generators]] of ECMAscript 6 (ES6), see http://wiki.ecmascript.org/doku.php?id=harmony:generators
- Generator on MDN (Mozilla Developer Network), see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator (With several broken links)
- Twisted-CSP: https://pypi.python.org/pypi/twisted-csp/, «Go-style channels for Twisted»
- Go Space Monkey: https://www.spacemonkey.com/blog/posts/go-space-monkey. This is discussed at golang-nuts, see https://groups.google.com/forum/#!topic/golang-nuts/rZ0Pix-S08E «Space Monkey dumps Python for Go».
- Chrome 39 Beta: JS Generators, Animation Playback Control, and the WebApp Manifest: http://blog.chromium.org/2014/10/chrome-39-beta-js-generators-animation.html. This was pointed tp by a page in Norwegian at digi.no by Harald Brombach: «Enklere asynkron koding med Chrome», see http://www.digi.no/930881/enklere-asynkron-koding-med-chrome
- Clojure – Concurrent programming, see http://clojure.org/concurrent_programming. Also see https://www.youtube.com/user/ClojureTV for a lot of lectures
- Clojure core.async Channels by Rich Hickey (2013) see https://clojure.org/news/2013/06/28/clojure-clore-async-channels
- Clojure core.async, lecture (45 mins). Rich Hickey discusses the motivation, design and use of the Clojure core.async library. See http://www.infoq.com/presentations/clojure-core-async (dead url) (url Nov2020) https://www.infoq.com/presentations/clojure-core-async/ (lecture 22Nov2013) and https://clojure.org/news/2013/06/28/clojure-clore-async-channels (description). Additionally you can download the soundtrack from this as an mp3.
Minutes into the lecture:
13.57 – CSP background
18.24 – The difference between blocking and parking. Also about IOC threads (Inversion of Control threads). See note 92 about this (here)
19.12 – The description of the difference between blocking and parking
- Implementation details of core.async Channels (lecture 35 mins + questions 20 mins) by Rich Hickey, at euroclojure (2014), see http://vimeo.com/100518968 (lecture) and http://cdn.cognitect.com/presentations/2014/insidechannels.pdf (slides)
- core.async/examples/walkthrough.clj, see https://github.com/clojure/core.async/blob/b6a9c113c95c2b90a32507c1751343c0cc023d89/examples/walkthrough.clj#L35
- Timothy Baldridge on Clojure’s Core.Async, see http://www.infoq.com/interviews/baldridge-core-async. From the transcript: «For those that are familiar with perhaps async/await in C#, how that works, it’s very, very close»
- 15 technologies changing how developers work by Peter Wayner @ InfoWorld (2014), see http://www.infoworld.com/article/2608467/development-tools/15-technologies-changing-how-developers-work.html?page=3
- What does the “yield” keyword do in Python ,see http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python
- Python generators, see https://wiki.python.org/moin/Generators
- aPyCSP – Asynchronous PyCSP Using Python Coroutines and asyncio by John Markus Bjørndalen (Department of Computer Science, University of Tromsø), Brian Vinter (Niels Bohr Institute, University of Copenhagen), Otto J. Anshusa (Department of Computer Science, University of Tromsø), at CPA 2018 in Dresden. See http://wotug.cs.unlv.edu/generate-program.php?id=46#paper376
- Python Tasks and coroutines, see https://docs.python.org/3/library/asyncio-task.html
- Red and Green callbacks by JOE ARMSTRONG at his blog «Erlang and other stuff» (2013). Read at https://joearms.github.io/#2013-04-02%20Red%20and%20Green%20callbacks