proj-plbook-plChSequencingAroundCommunication

Table of Contents for Programming Languages: a survey

Chapter: sequencing around communication

receiving data

blocking

always use timeouts!

callbacks

and futures etc

callbacks

con: "...the cumbersome use of callbacks. This, of course, is a problem with many asynchronous computations: you gain concurrency but lose the natural code flow. It’s hard for a programmer to reason about which line of code executes on which thread, and passing information from one callback to another is cumbersome as well." -- http://blog.paralleluniverse.co/post/64210769930/spaceships2

TJ Holowaychuk describes how callbacks can be more error-prone than some other concurrency techniques:

"In Go when my code is done, it’s done, you can’t get re-execute the statement. This is not true in Node, you could think a routine is completely finished, until a library accidentally invokes a callback multiple times, or doesn’t properly clear handlers, and cause code to re-execute." [1]

todo: i think: With callbacks, programmers can forget to propagate errors, leading to an error crashing a thread without the rest of the program noticing.

futures

An alternative to callbacks that allows you to write the code in an easier-to-read manner.

'promises' are used somewhat interchangably, although some languages have both 'promises' and 'futures' and distinguish between them

implicit (it's just a value from the program's point of view) vs. explicit (it's a structure that you query to see if it's been bound yet)

in some languages, the writable side of the future is separated from the readable side (like a pipe). This allows you to e.g. copy the readable side and pass it to 5 consumers, and pass the writable side to 1 producer, without fearing that one of the consumers will overstep their authority and try to write to the future.

in clojure, it's easy to make futures behave like ordinary variables, because stateful variables must be 'deref'd anyway

clojure has something called a 'promise' and something called a 'future'. The difference is that with a clojure 'future', at the time of future creation you bind an expression that will be evaluated to give the result; whereas with a clojure 'promise', the promise is just a structure that you later bind a result to, e.g. the computation that will produce the result need not be determined yet at the time of promise creation. (see http://stackoverflow.com/questions/4623536/how-do-clojure-futures-and-promises-differ ). Promises are read-only. (this terminology is flipped in the C++ Folly Futures library [2])

in c++, futures are (see http://stackoverflow.com/questions/12620186/futures-vs-promises ) the read side and promises are the write side.

A hardware version is full/empty bits, found for example in the https://en.wikipedia.org/wiki/Cray_MTA : "For example, an array A is initially written with "empty" bits, and any thread reading a value from A blocks until another thread writes a value.". In the Cray MTA, the blocking on empty bits eventually times out. Opcodes are provided which ignore full/empty status.

There is a standard for promises in Javascript, http://promisesaplus.com/ . It was referenced by https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 , so perhaps it is canonical.

facebook's C++ Folly Futures library has a good explanation of various things (if you can read C++):

some constructs in the Folly library mentioned in that introduction are:

Rust futures:

await

C# await: http://msdn.microsoft.com/en-us/library/hh156528.aspx

the idea is that if you have a promise, you give that promise to the 'await' keyword, which puts the current block of code 'on hold' until the promise completes, and in the meantime yields control to YOUR caller.

Python 3.5's async/await:

Javascript's (contrasted with callbacks, and (raw) promises):

labeled lines

like neuro -- always have an answer even if your inputs aren't ready (the answer can be 'i don't know')

sending data

yield (and generators)

(just like in the serial case with coroutines)

return

(just like in the serial case)

send a message thru a channel

alternative: callbacks

pub/sub

alter a 'shared' memory

events

generalize to unordered eventcounts (cite Unify: A scalable, loosely-coupled, distributed shared memory multicomputer; that article reserves the term 'eventual consistency' when there is a maximum time duration until consistency)

condition variable

supports 3 operations

wait: go to sleep until you get woken (see below)

signal: wake one thread waiting on condVar

broadcast: wake all threads waiting on condVar

example usage: producer/consumer: Every now and then, the producer sends some data, and then the consumer is supposed to do something with it. It would be a waste of time for the consumer to busy wait for new data. Solution: The producer signals the condition variable when they produce something. the consumer sleeps on the condition then wakes up and processes what the producer produced.

todo should this also be mentioned in 'locks and friends'?

dataflow

? or should this be in a different chapter

Data Flow and Systolic Array Architectures, "Computer Architecture" Chapter 8, M.Zargham

event-driven programming, pub/sub

? or should this be in a different chapter

streams and reactive programming

'observable' = 'stream'

you can treat streams like lazy lists; you can filter and map over streams

a promise is a stream with only one event to be emitted on it

to apply an async operation (which returns a 'promise' type of stream) to a stream, you flatmap that operation over the stream; this (a) maps the operation over the stream, transforming each event (input to the async operation) into a promise stream (output of the async operation), (b) takes the resulting stream of streams and flattens (merges) it into one stream (since each promise stream only had one event on it, each one will contribute one event to the final, flattened stream)

Links:

spreadsheet-like dependent updates

? should this be subsumed under dataflow or event-driven programming? ? maybe not: a key feature two-way (symmetric) updates or even cyclic dependencies

Links: