diff options
| author | Heather Miller <heather.miller@epfl.ch> | 2017-01-06 18:57:10 +0100 |
|---|---|---|
| committer | Heather Miller <heather.miller@epfl.ch> | 2017-01-06 18:57:10 +0100 |
| commit | 190eaa4db282b8772915daf36f766ee415c7ddb3 (patch) | |
| tree | f5f9fbeb98f6411cdf0c7e127e5d6fdf01292056 | |
| parent | b1cf13492f56b96a0ef44918757222f4a0133b1a (diff) | |
Finished tweaking history section
| -rw-r--r-- | _bibliography/futures.bib | 91 | ||||
| -rw-r--r-- | chapter/2/futures.md | 17 |
2 files changed, 81 insertions, 27 deletions
diff --git a/_bibliography/futures.bib b/_bibliography/futures.bib index b606a79..8cb712b 100644 --- a/_bibliography/futures.bib +++ b/_bibliography/futures.bib @@ -44,24 +44,7 @@ address = {New York, NY, USA}, } -@inproceedings{2, - author = {Liskov, B. and Shrira, L.}, - title = {Promises: Linguistic Support for Efficient Asynchronous Procedure Calls in Distributed Systems}, - booktitle = {Proceedings of the ACM SIGPLAN 1988 Conference on Programming Language Design and Implementation}, - series = {PLDI '88}, - year = {1988}, - isbn = {0-89791-269-1}, - location = {Atlanta, Georgia, USA}, - pages = {260--267}, - numpages = {8}, - url = {http://doi.acm.org/10.1145/53990.54016}, - doi = {10.1145/53990.54016}, - acmid = {54016}, - publisher = {ACM}, - address = {New York, NY, USA}, -} - -@article{3, +@article{Promises88, author = {Liskov, B. and Shrira, L.}, title = {Promises: Linguistic Support for Efficient Asynchronous Procedure Calls in Distributed Systems}, journal = {SIGPLAN Not.}, @@ -80,6 +63,17 @@ address = {New York, NY, USA}, } +@article{Argus88, + title={Distributed programming in Argus}, + author={Liskov, Barbara}, + journal={Communications of the ACM}, + volume={31}, + number={3}, + pages={300--312}, + year={1988}, + publisher={ACM} +} + @article{4, author = {Eriksen, Marius}, title = {Your Server As a Function}, @@ -338,7 +332,7 @@ address = {Cambridge, MA, USA}, } -@inproceedings{37, +@inproceedings{ELang, author = {Miller, Mark S. and Tribble, E. Dean and Shapiro, Jonathan}, title = {Concurrency Among Strangers: Programming in E As Plan Coordination}, booktitle = {Proceedings of the 1st International Conference on Trustworthy Global Computing}, @@ -354,6 +348,49 @@ address = {Berlin, Heidelberg}, } +@article{PromisePipe07, + title={The Promise System}, + author = {Miller, Mark S. and Tribble, E. Dean and Jellinghaus, Rob}, + journal={Presentation}, + url = {http://web.archive.org/web/20071023111712/http://www.sunless-sea.net/Transcripts/promise.html}, + year={2007} +} + +@techreport{Joule, + title={Joule: Distributed application foundations}, + author={Tribble, E. Dean and Miller, Mark S. and Hardy, Norm and Krieger, David}, + number={ADd003.4P}, + institution={Agorics, Inc.}, + url={http://www.erights.org/history/joule/MANUAL.BK2.pdf}, + year={1995} +} + +@misc{Twisted, + author = {Glyph Lefkowitz}, + title = {Twisted}, + year = {2002}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/twisted/twisted}} +} + +@misc{Qjs, + author = {Kris Kowal}, + title = {Q.js}, + year = {2009}, + publisher = {GitHub}, + journal = {GitHub repository}, + howpublished = {\url{https://github.com/kriskowal/q}} +} + +@online{JQueryPromises, + author = {Valerio Gheri}, + title = {JavaScript Promises and Why JQuery Implementation is Broken}, + year = 2013, + url = {\url{https://thewayofcode.wordpress.com/tag/jquery-deferred-broken/}}, + urldate = {2017-01-06} +} + @INPROCEEDINGS{38, author = {Didier Le Botlan and Guido Tack and Andreas Rossberg and Andreas Rossberg and Didier Le and Botlan Guido Tack and Thorsten Brunklaus and Thorsten Brunklaus and Gert Smolka and Gert Smolka}, title = {Alice through the looking glass}, @@ -385,6 +422,22 @@ year={2013} } + +@article{PromisesA, + title={CommonJS Promises/A Specification}, + author={Kris Zyp}, + journal={Promises/A Specification}, + url = {http://wiki.commonjs.org/wiki/Promises/A}, + year={2009} +} + +@misc{Ecmascript15, + title={ECMAScript Language Specification}, + author={ECMAScript, ECMA and European Computer Manufacturers Association and others}, + year={2015} +} + + @misc{40, title={Futures and promises}, url = {https://en.wikipedia.org/wiki/Futures_and_promises} diff --git a/chapter/2/futures.md b/chapter/2/futures.md index f0f81e0..84d7254 100644 --- a/chapter/2/futures.md +++ b/chapter/2/futures.md @@ -59,7 +59,7 @@ However promises and futures are considered useful in a number of contexts as we - **Input/Output**, such as UI dialogs requiring user input, or operations such as reading large files from disk. A future may be used to represent the IO call and the resulting value of the IO (e.g., terminal input, array of bytes of a file that was read). - **Long-Running Computations**. Imagine you would like the process which initiated a long-running computation, such as a complex numerical algorithm, not to wait on the completion of that long-running computation and to instead move on to process some other task. A future may be used to represent this long-running computation and the value of its result. - **Database Queries**. Like long-running computations, database queries can be time-consuming. Thus, like above, it may be desirable to offload the work of doing the query to another process and move on to processing the next task. A future may be used to represent the query and resulting value of the query. -- **RPC**. Network latency is typically an issue when making an RPC call to a server. Like above, it may be desirable to not have to wait on the result of the RPC invocation by instead offloading it to another process. A future may be used to represent the RPC call and its result; when the server responds with a result, the future is completed and its value is the server's response. +- **RPC (Remote Procedure Call)**. Network latency is typically an issue when making an RPC call to a server. Like above, it may be desirable to not have to wait on the result of the RPC invocation by instead offloading it to another process. A future may be used to represent the RPC call and its result; when the server responds with a result, the future is completed and its value is the server's response. - **Reading Data from a Socket** can be time-consuming particularly due to network latency. It may thus be desirable to not to have to wait on incoming data, and instead to offload it to another process. A future may be used to represent the reading operation and the resulting value of what it reads when the future is completed. - **Timeouts**, such as managing timeouts in a web service. A future representing a timeout could simply return no result or some kind of empty result like the `Unit` type in typed programming languages. @@ -102,7 +102,7 @@ And confusingly, the JavaScript community has standardized on a single construct As we can see, concepts, semantics, and terminology seem to be a bit mixed up between languages and library implementations of futures/promises. These differences in terminology and semantics arise from the long history and independent language communities that have proliferated the use of futures/promises. -## History +## Brief History Here's a brief glimpse at a timeline spanning the history of futures and promises as we know them today: @@ -130,18 +130,19 @@ In their paper, Baker and Hewitt introduced a notion of Futures as a 3-tuple rep Though importantly, the focus of their work was not on role of futures and the role they play in asynchronous distributed computing. Instead, it was focused on garbage collecting the processes which evaluate expressions that were not needed by the function. -The Multilisp language, presented by Halestead in 1985 built upon this call-by-future with a Future annotation. Binding a variable to a future expression creates a process which evaluates that expression and binds x to a token which represents its (eventual) result. It allowed an operation to move past the actual computation without waiting for it to complete. If the value is never used, the current computation will not pause. MultiLisp also had a lazy future construct, called Delay, which only gets evaluated when the value is first required. +The Multilisp language {% cite Multilisp --file futures %}, presented by Halestead in 1985 built upon this call-by-future with a future annotation. In Multilisp, binding a variable to a future expression would in turn create a new process which evaluates that expression and binds it to the variable reference which represents its (eventual) result. That is, Multilisp introduced a way to compute arbitrary expressions concurrently in a new process. This made it possible to move past the actual computation and continue processing without waiting for the future to complete. If the result value of the future is never used, the initiating process will not block, thus eliminating a potential source of deadlock. MultiLisp also included a lazy future variant, called _delay_, which would only be evaluated the first time the value is required elsewhere in the program. - This design of futures influenced the paper of design of Promises in Argus by Liskov and Shrira in 1988. Both futures in MultiLisp and Promises in Argus provisioned for the result of a call to be picked up later. Building upon the initial design of Future in MultiLisp, they extended the original idea by introducing strongly typed Promises and integration with call streams. Call streams are a language-independent communication mechanism connecting a sender and a receiver in a distributed programming environment. It is used to make calls from sender to receiver like normal RPC. In addition, sender could also make stream-calls where it chooses to not wait for the reply and can make further calls. Stream calls seem like a good use-case for a placeholder to access the result of a call in the future : Promises. Call streams also had provisions for handling network failures. This made it easier to handle exception propagation from callee to the caller and also to handle the typical problems in a multi-computer system. This paper also talked about stream composition. The call-streams could be arranged in pipelines where output of one stream could be used as input on next stream. This notion is not much different to what is known as promise pipelining today, which will be introduced in more details later. +This design of futures in Multilisp in turn influenced a construct dubbed _promises_ in the Argus programming language {% cite Promises88 Argus88 --file futures %} by Liskov and Shrira in 1988. Like futures in MultiLisp, promises in Argus intended to be a placeholder for the result of a value that will be available in the future. Unlike Multilisp which was focused on single-machine concurrency, however, Argus was designed to facilitate distributed programming, and in particular focused on promises as a way to integrate _asynchronous_ RPC into the Argus programming language. Importantly, promises were extended beyond futures in Multilisp through the introduction of types to promises. Therefore, in Argus, when a call to `promise` is made, a promise is created which immediately returns, and a type-safe asynchronous RPC call is made in a new process. When the RPC completes, the returned value can be claimed by the caller. +Argus also introduced call streams, which can be thought of as a way to enforce an ordering of concurrently executing calls. A sender and a receiver are connected by a stream, over which it is possible make normal (synchronous) RPC calls, or _stream calls_, in which the sender may make more calls before receiving the reply. The underlying runtime however ensures that, despite the non-blocking stream calls fired off, that all calls and subsequent replies happen in call order. That is, call-streams ensure exactly-once, ordered delivery. Argus also introduces constructs to _compose_ call-streams, in order to build up pipelines of computation, or directed acyclic graphs (DAGs) of computation. These semantics are an early precursor to what we refer to today as _promise pipelining_. -E is an object-oriented programming language for secure distributed computing, created by Mark S. Miller, Dan Bornstein, and others at Electric Communities in 1997. One of the major contribution of E was the first non-blocking implementation of Promises. It traces its routes to Joule which was a dataflow programming language. E had an eventually operator, `* <- *` . This created what is called an eventual send in E : the program doesn't wait for the operation to complete and moves to next sequential statement. Eventual-sends queue a pending delivery and complete immediately, returning a promise. A pending delivery includes a resolver for the promise. Further messages can also be eventually send to a promise before it is resolved. These messages are queued up and forwarded once the promise is resolved. The notion of promise pipelining in E is also inherited from Joule. +E is an object-oriented programming language for secure distributed computing {% cite ELang --file futures %}, created by Mark S. Miller, Dan Bornstein, and others at Electric Communities in 1997. A major contribution of E is its interpretation and implementation of promises. It traces its routes to Joule {% cite Joule --file futures %}, a dataflow programming language predecessor to E. Importantly, E introduced an _eventually_ operator, `* <- *` which enabled what is called an eventual send in E; that is, the program doesn't wait for the operation to complete and moves to next sequential statement. This is in contrast to the expected semantics of an _immediate call_ which looks like a normal method invocation in E. Eventual sends queue a pending delivery and complete immediately, returning a promise. A pending delivery includes a resolver for the promise. Subsequent messages can also be eventually sent to a promise before it is resolved. In this case, these messages are queued up and forwarded once the promise is resolved. That is, once we have a promise, we are able to chain make several pipelined eventual sends as if the initial promise was already resolved. This notion of _promise pipelining_ {% cite PromisePipe07 --file futures %} has been adopted by a majority of contemporary futures/promises interpretations. +Futures and promises remained primarily an academic fascination until the early 2000s, upon the rise of web application development, networked system development, and an increased need for responsive user interfaces. -Among the modern languages, Python was perhaps the first to come up with something on the lines of E’s promises with the Twisted library. Coming out in 2002, it had a concept of Deferred objects, which were used to receive the result of an operation not yet completed. They were just like normal objects and could be passed along, but they didn’t have a value. They supported a callback which would get called once the result of the operation was complete. +Among the mainstream programming languages, Python was perhaps the first, in 2002, to get a library which introduced a construct along the same lines as E’s promises in the Twisted library {% cite Twisted --file futures %}. Twisted introduced the notion of _Deferred_ objects, are used to receive the result of an operation not yet completed. In Twisted, deferred objects are just like normal first-class objects; they can be passed along anywhere a normal object can, the only difference is that deferred objects don't have values. Deferred objects support callbacks, which are called once the result of the operation is complete. - -Promises and javascript have an interesting history. In 2007 inspired by Python’s twisted, dojo came up with it’s own implementation of of dojo.Deferred. This inspired Kris Zyp to then come up with the CommonJS Promises/A spec in 2009. Ryan Dahl introduced the world to NodeJS in the same year. In it’s early versions, Node used promises for the non-blocking API. When NodeJS moved away from promises to its now familiar error-first callback API (the first argument for the callback should be an error object), it left a void for a promises API. Q.js was an implementation of Promises/A spec by Kris Kowal around this time. FuturesJS library by AJ ONeal was another library which aimed to solve flow-control problems without using Promises in the strictest of senses. In 2011, JQuery v1.5 first introduced Promises to its wider and ever-growing audience. The API for JQuery was subtly different than the Promises/A spec. With the rise of HTML5 and different APIs, there came a problem of different and messy interfaces which added to the already infamous callback hell. A+ promises aimed to solve this problem. From this point on, leading from widespread adoption of A+ spec, promises was finally made a part of ECMAScript® 2015 Language Specification. Still, a lack of backward compatibility and additional features provided means that libraries like BlueBird and Q.js still have a place in the javascript ecosystem. +Perhaps most famous in recent memory is that of promises in JavaScript. In 2007, inspired by Python’s Twisted library, the authors of the Dojo Toolkit came up a JavaScript implementation of Twisted's deferred objects, known as `dojo.Deferred`. This in turn inspired Kris Zyp to propose the CommonJS Promises/A spec in 2009 {% cite PromisesA --file futures %}. The same year, Ryan Dahl introduced NodeJS. In it’s early versions, Node used promises in its non-blocking API. However, when NodeJS moved away from promises to its now familiar error-first callback API (the first argument for the callback should be an error object), it left a void to fill for a promises API. [Q.js](https://github.com/kriskowal/q) is an implementation of Promises/A spec by Kris Kowal around this time {% cite Qjs --file futures %}. The [FuturesJS](https://github.com/FuturesJS/FuturesJS) library by AJ O'Neal was another library which aimed to solve flow-control problems without using Promises in the strictest of senses. In 2011, JQuery v1.5 introduced Promises to its wider and ever-growing audience. However, JQuery's promises API was subtly different than the Promises/A spec {% cite JQueryPromises --file futures %}. With the rise of HTML5 and different APIs, there came a problem of different and messy interfaces which added to the already infamous callback hell. The Promises/A+ spec {% cite PromisesAPlus --file futures %} aimed to solve this problem. Following the broad community acceptance of the Promises/A+ spec, promises were finally made a part of the ECMAScript® 2015 Language Specification {% cite Ecmascript15 --file futures %}. However, a lack of backward compatibility and additional features missing in the Promises/A+ spec means that libraries like [BlueBird](http://bluebirdjs.com/docs/getting-started.html) and [Q.js](https://github.com/kriskowal/q) still have a place in the JavaScript ecosystem. ## Semantics of Execution |
