Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Futures and promises block the derefing thread. Once that is somewhat mitigated by notifying promises, we then get callback hell and inversion of control. These issues The same issues exist in Javascript. These issues were addressed by F#, and later C# async/await, the latter of which has been copied by Scala. The same issues exist in Javascript. 

Proposal

Copy C# async/await. (async ...) establishes a block, within which (await a-future-or-promise) will relinquish control, wiring up a state machine representing the rest of the block to the notification of the future/promise. The async block itself returns a promise.

...

It will also require an ambient thread pool.

 

Implementation Notes

This proposal has been coded up and the result is available here: https://github.com/relevance/clojure/tree/core-futures Note: the implementation of futures should be considered in "draft" phase, it will change radically before an alpha is released. 


There are 4 major steps to this implementation:


1) The expression inside the state-machine macro is transversed

2) For each node an instruction for a virtual machine is recorded

3) These instructions (in a SSA style block format) are analyzed to find temporary variables

4) The instructions are emitted as a state machine. 

5) The state machine is wrapped by functions that pack and unpack tasks



The output of the state machine macro is a function that takes an old state and produces a new state. Thus these state machines are immutable, and side affect free (assuming the code in them is also side-effect free). 


Work to be done:

  • Think about try/catch/finally, doesn't work at the moment
  • Don't overload the deref value, instead we will use await to deref listenable futures
  • Remove generator code, it could be confusing to new users
  • Decide on a good future/promise library (WIP)