![Page 1: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/1.jpg)
futures&promisesin Scala 2.10
PHILIPP HALLERHEATHER MILLER
![Page 2: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/2.jpg)
Futures/PromisesAgenda
Execution CtxstRY
![Page 3: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/3.jpg)
common theme:
![Page 4: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/4.jpg)
common theme:Pipelining
![Page 5: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/5.jpg)
future&promise
scala.concurrent.
![Page 6: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/6.jpg)
First, some Motivation
![Page 7: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/7.jpg)
1Several important libraries have their own future/promise implementation
![Page 8: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/8.jpg)
1Several important libraries have their own future/promise implementation
java.util.concurrent.scala.actors.
com.twitter.util.
akka.dispatch.scalaz.concurrent.net.liftweb.actor.
FUTUREFUTUREFUTURE
FUTUREPROMISELAFUTURE
![Page 9: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/9.jpg)
This makes it clear that...
![Page 10: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/10.jpg)
This makes it clear that...
futures are an important, powerful abstraction
![Page 11: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/11.jpg)
This makes it clear that...
futures are an important, powerful abstraction
there’s fragmentation in
the scala ecosystem
no hope of interop!
![Page 12: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/12.jpg)
Furthermore...
![Page 13: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/13.jpg)
Furthermore...Java futures neither efficient nor composable2
![Page 14: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/14.jpg)
Furthermore...Java futures neither efficient nor composable2we could make futures more powerful, by taking advantage of scala’s features
3
![Page 15: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/15.jpg)
can be thought of as a single concurrency abstraction
Futures&Promises
Future promise
![Page 16: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/16.jpg)
can be thought of as a single concurrency abstraction
Futures&Promises
Future
READ-MANY
promise
write-once
![Page 17: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/17.jpg)
can be thought of as a single concurrency abstraction
Futures&Promises
Future
READ-MANY
promise
write-once
Start async computation ✔important ops
Assign result value✔ Wait for result ✔ Obtain associated future object
✔
![Page 18: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/18.jpg)
a promise p of type Promise[T] can be completed in two ways...
Success&Failure
val result: T = ...p.success(result)
Success
val exc = new Exception(“something went wrong”)p.failure(exc)
Failure
![Page 19: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/19.jpg)
FuturePromiseFuture with value
GreenRed thread waiting on the
result of another thread
meaningful work
java.util.concurrent.future
![Page 20: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/20.jpg)
java.util.concurrent.future
FuturePromiseFuture with value
GreenRed thread waiting on the
result of another thread
meaningful work
![Page 21: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/21.jpg)
what we’d like to do instead
FuturePromiseFuture with value
GreenRed thread waiting on the
result of another thread
meaningful work
![Page 22: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/22.jpg)
Async&NonBlocking
![Page 23: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/23.jpg)
Async&NonBlockinggoal: Do not block current thread while waiting
for result of future
![Page 24: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/24.jpg)
Async&NonBlockinggoal: Do not block current thread while waiting
for result of future
CallbacksRegister callback which is invoked (asynchronously) when future is completed
Async computations never block(except for managed blocking)
![Page 25: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/25.jpg)
Async&NonBlockinggoal: Do not block current thread while waiting
for result of future
CallbacksRegister callback which is invoked (asynchronously) when future is completed
Async computations never block(except for managed blocking)
user doesn’t have to explicitly manage
callbacks. higher-order functions instead!
![Page 26: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/26.jpg)
Futures&PromisesThread1 Thread2 Thread3
example
![Page 27: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/27.jpg)
Futures&Promises
Promise
val p = Promise[Int]() // Thread 1
Thread1 Thread2 Thread3
(create promise)
example
![Page 28: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/28.jpg)
Futures&Promises
PromiseFuture
val p = Promise[Int]() // Thread 1val f = p.future // Thread 1
Thread1 Thread2 Thread3
(create promise)(get reference to future)
example
![Page 29: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/29.jpg)
Futures&Promises
PromiseFuture
val p = Promise[Int]() // Thread 1val f = p.future // Thread 1
f onSuccess { // Thread 2 case x: Int => println(“Successful!”)}
Thread1 Thread2 Thread3
onSuccess callback
(create promise)(get reference to future)(register callback)
example
![Page 30: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/30.jpg)
Futures&Promises
PromiseFuture
val p = Promise[Int]() // Thread 1val f = p.future // Thread 1
f onSuccess { // Thread 2 case x: Int => println(“Successful!”)}
Thread1 Thread2 Thread3
onSuccess callback
p.success(42) // Thread 1
4242
(create promise)(get reference to future)(register callback)
(write to promise)
example
![Page 31: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/31.jpg)
Futures&Promises
PromiseFuture
val p = Promise[Int]() // Thread 1val f = p.future // Thread 1
f onSuccess { // Thread 2 case x: Int => println(“Successful!”)}
Thread1 Thread2 Thread3
onSuccess callback
p.success(42) // Thread 1
4242 Successful!
Console
(create promise)(get reference to future)(register callback)
(write to promise)
(execute callback)// Thread
example
note: onSuccess callback executed even if f has
already been completed at time of registration
![Page 32: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/32.jpg)
Combinators
val purchase: Future[Int] = rateQuote map { quote => connection.buy(amount, quote) }
val postBySmith: Future[Post] = post.filter(_.author == “Smith”)
Composability thru higher-order funcsstandard monadic combinators
def map[S](f: T => S): Future[S]
def filter(pred: T => Boolean): Future[T]
![Page 33: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/33.jpg)
Combinators
val purchase: Future[Int] = rateQuote map { quote => connection.buy(amount, quote) }
val postBySmith: Future[Post] = post.filter(_.author == “Smith”)
Composability thru higher-order funcsstandard monadic combinators
def map[S](f: T => S): Future[S]
def filter(pred: T => Boolean): Future[T]
If filter fails: postBySmith completed with NoSuchElementException
If map fails: purchase is completed with unhandled exception
![Page 34: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/34.jpg)
CombinatorsAdditional future-specific higher-order functions have been introduced
def fallbackTo[U >: T](that: Future[U]): Future[U]
val fut: Future[T] = Future.firstCompletedOf[T](futures)
def andThen(pf: PartialFunction[...]): Future[T]
![Page 35: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/35.jpg)
CombinatorsAdditional future-specific higher-order functions have been introduced
def fallbackTo[U >: T](that: Future[U]): Future[U]
val fut: Future[T] = Future.firstCompletedOf[T](futures)
def andThen(pf: PartialFunction[...]): Future[T]
”falls back” to that future in case of failure
returns a future completed with result of first completed future
allows one to define a sequential execution over a chain of futures
![Page 36: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/36.jpg)
contextExecution
scala.concurrent.
![Page 37: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/37.jpg)
are needed by:Threadpools...
futures
Actors
parallel collections
for executing callbacks and function arguments
for executing message handlers, scheduled tasks, etc.
for executing data-parallel operations
![Page 38: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/38.jpg)
contextsExecution
Scala 2.10 introduces
![Page 39: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/39.jpg)
contextsExecution
Scala 2.10 introduces
provide global threadpool as platform service to be shared by all parallel frameworks
Goal
![Page 40: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/40.jpg)
contextsExecution
Scala 2.10 introduces
provide global threadpool as platform service to be shared by all parallel frameworks
Goal
scala.concurrent package provides global ExecutionContext
Default ExecutionContext backed by the most recent fork join pool (collaboration with Doug Lea, SUNY Oswego)
![Page 41: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/41.jpg)
Implicit Execution Ctxsdef map[S](f: T => S)(implicit executor: ExecutionContext): Future[S]
def onSuccess[U](pf: PartialFunction[T, U]) (implicit executor: ExecutionContext): Unit
Asynchronous computations are executed on an ExecutionContext which is provided implicitly.
Implicit parameters enable fine-grained selection of the ExecutionContext:
implicit val context: ExecutionContext = customExecutionContextval fut2 = fut1.filter(pred) .map(fun)
![Page 42: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/42.jpg)
Implicit Execution Ctxsdef map[S](f: T => S)(implicit executor: ExecutionContext): Future[S]
def onSuccess[U](pf: PartialFunction[T, U]) (implicit executor: ExecutionContext): Unit
Asynchronous computations are executed on an ExecutionContext which is provided implicitly.
Implicit parameters enable fine-grained selection of the ExecutionContext:
implicit val context: ExecutionContext = customExecutionContextval fut2 = fut1.filter(pred) .map(fun)
implicit ExecutionContexts allow sharing ecs
between frameworks
Enables flexible selection of execution policy
![Page 43: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/43.jpg)
Futurethe implementation
def map[S](f: T => S): Future[S] = { val p = Promise[S]()
onComplete { case result => try { result match { case Success(r) => p success f(r) case Failure(t) => p failure t } } catch { case t: Throwable => p failure t } } p.future}
Many operations implemented in terms of promisessimplified example
![Page 44: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/44.jpg)
Futurethe implementationREAL
def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { val p = Promise[S]()
onComplete { case result => try { result match { case Success(r) => p success f(r) case f: Failure[_] => p complete f.asInstanceOf[Failure[S]] } } catch { case NonFatal(t) => p failure t } } p.future}
The real implementation (a) adds an implicit ExecutionContext, (b) avoids extra object creations, and (c) catches only non-fatal exceptions:
![Page 45: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/45.jpg)
Promisethe implementation
Promise is the work horse of the futures implementation.
def complete(result: Try[T]): this.type = if (tryComplete(result)) this else throw new IllegalStateException("Promise already completed.")
A Promise[T] can be in one of two states:
COMPLETED
PENDINGNo result has been written to the promise.State represented using a list of callbacks (initially empty).
The promise has been assigned a successful result or exception.State represented using an instance of Try[T]
Invoking Promise.complete triggers a transition from state Pending to Completed
A Promise can be completed at most once:
![Page 46: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/46.jpg)
def tryComplete(value: Try[T]): Boolean = { val resolved = resolveTry(value) (try { @tailrec def tryComplete(v: Try[T]): List[CallbackRunnable[T]] = { getState match { case raw: List[_] => val cur = raw.asInstanceOf[List[CallbackRunnable[T]]] if (updateState(cur, v)) cur else tryComplete(v) case _ => null } } tryComplete(resolved) } finally { synchronized { notifyAll() } // Notify any blockers }) match { case null => false case rs if rs.isEmpty => true case rs => rs.foreach(_.executeWithValue(resolved)); true }}
Completing a Promise
![Page 47: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/47.jpg)
the awkWard squadabstract class AbstractPromise { private volatile Object _ref; final static long _refoffset; static { try { _refoffset = Unsafe.instance.objectFieldOffset( AbstractPromise.class.getDeclaredField("_ref")); } catch (Throwable t) { throw new ExceptionInInitializerError(t); } } protected boolean updateState(Object oldState, Object newState) { return Unsafe.instance.compareAndSwapObject(this, _refoffset, oldState, newState); } protected final Object getState() { return _ref; }}
![Page 48: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/48.jpg)
IntegratingFutures Actors&Futures are results of asynchronous message sends when a response is expected
Future of Friends is either completed with a successful result or with a wrapped exception if response times out or is not of type Seq[Friend]
val response: Future[Any] = socialGraph ? getFriends(user)
Implementing synchronous send (untyped):
def syncSend(to: ActorRef, msg: Any, timeout: Duration): Any = { val fut = to ? msg Await.result(fut, timeout)}
Recovering typesval friendsFut: Future[Seq[Friend]] = response.mapTo[Seq[Friend]]
![Page 49: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/49.jpg)
IntegratingFutures Actors&Futures are results of asynchronous message sends when a response is expected
Future of Friends is either completed with a successful result or with a wrapped exception if response times out or is not of type Seq[Friend]
val response: Future[Any] = socialGraph ? getFriends(user)
Implementing synchronous send (untyped):
def syncSend(to: ActorRef, msg: Any, timeout: Duration): Any = { val fut = to ? msg Await.result(fut, timeout)}
Recovering typesval friendsFut: Future[Seq[Friend]] = response.mapTo[Seq[Friend]]
friendsFut is either completed with a successful result or with a wrapped exception if response times out or is not of type Seq[Friend]
![Page 50: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/50.jpg)
TRYscala.util.
![Page 51: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/51.jpg)
And now onto something completely different.
![Page 52: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/52.jpg)
And now onto something completely different.
not concurrent,
not asynchronous
![Page 53: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/53.jpg)
Tryis a simple data container
Composable✔Combinators for exceptions✔
Great for monadic-style exception handling.
Divorcing exception handling from the stack.
![Page 54: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/54.jpg)
Tryis a simple data container
sealed abstract class Try[+T]
final case class Success[+T](value: T) extends Try[T]
final case class Failure[+T](exception: Throwable) extends Try[T]
![Page 55: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/55.jpg)
Tryis a simple data container
sealed abstract class Try[+T]
final case class Success[+T](value: T) extends Try[T]
final case class Failure[+T](exception: Throwable) extends Try[T]
![Page 56: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/56.jpg)
Tryis a simple data container
sealed abstract class Try[+T]
final case class Success[+T](value: T) extends Try[T]
final case class Failure[+T](exception: Throwable) extends Try[T]
![Page 57: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/57.jpg)
Trymethods onBasic Ops
def get: T
get
Success
Failure
Returns value stored within Success
Throws exception stored within Failure
![Page 58: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/58.jpg)
Trymethods on
def getOrElse[U >: T](default: => U): U
Success
Failure
Returns value stored within Success
Returns the given default argument if this is a Failure
getOrElseBasic Ops
![Page 59: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/59.jpg)
Trymethods on
def orElse[U >: T](default: => Try[U]): Try[U]
orElse
Success
Failure
Returns this Try if this is a Success
Returns the given default argument if this is a Failure
Basic Ops
![Page 60: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/60.jpg)
Trymethods on
def map[U](f: T => U): Try[U]
map
Success
Failure
Applies the function f to the value from Success
Returns this if this is a Failure
monadic Ops
![Page 61: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/61.jpg)
Trymethods on
def flatMap[U](f: T => Try[U]): Try[U]
flatMap
Success
Failure
Applies the function f to the value from Success
Returns this if this is a Failure
monadic Ops
![Page 62: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/62.jpg)
Trymethods on
def filter(p: T => Boolean): Try[T]
filter
Success
Failure
Converts this to a Failure if predicate p not satisfied.
Returns this if this is a Failure
monadic Ops
![Page 63: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/63.jpg)
Trymethods on
def recoverWith[U >: T](f: PartialFunction[Throwable, Try[U]]): Try[U]
recoverWith
Success
Failure
Returns this if this is a Success
Applies function f if this is a Failure. (flatMap on exptn)
exception-specific Ops
![Page 64: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/64.jpg)
Trymethods on
def recover[U >: T](f: PartialFunction[Throwable, U]): Try[U]
recover
Success
Failure
exception-specific Ops
Returns this if this is a Success
Applies function f if this is a Failure. (map on exptn)
![Page 65: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/65.jpg)
Trymethods on
def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U]
transform
Success
Failure
Creates Try by applying function s if this is a Success
Creates Try by applying function f if this is a Failure
exception-specific Ops
![Page 66: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/66.jpg)
TO BUILDUSING THESE Pipelines
![Page 67: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/67.jpg)
TO BUILDUSING THESE Pipelines
Remember: not concurrent,
not asynchronous
![Page 68: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/68.jpg)
TrySimple pipelining onExample 1
case class Account(acctNum: Int, balance: Double, interestRate: Double)
val withdrawal = 1500val adjustment = 0.4val in = Try(getAcct)
val withdrawalResult = in map { (x: Account) => Account(x.acctNum, x.balance - withdrawal, x.interestRate) } filter { (x: Account) => x.balance > 12000 // acct in good standing } flatMap { (x: Account) => Account(x.acctNum, x.balance, x.interestRate + adjustment) Try(updateAcct) }
![Page 69: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/69.jpg)
TrySimple pipelining onExample 1
case class Account(acctNum: Int, balance: Double, interestRate: Double)
val withdrawal = 1500val adjustment = 0.4val in = Try(getAcct)
val withdrawalResult = in map { (x: Account) => Account(x.acctNum, x.balance - withdrawal, x.interestRate) } filter { (x: Account) => x.balance > 12000 // acct in good standing } flatMap { (x: Account) => Account(x.acctNum, x.balance, x.interestRate + adjustment) Try(updateAcct) }
GETACCT MIGHT FAIL
![Page 70: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/70.jpg)
TrySimple pipelining onExample 1
case class Account(acctNum: Int, balance: Double, interestRate: Double)
val withdrawal = 1500val adjustment = 0.4val in = Try(getAcct)
val withdrawalResult = in map { (x: Account) => Account(x.acctNum, x.balance - withdrawal, x.interestRate) } filter { (x: Account) => x.balance > 12000 // acct in good standing } flatMap { (x: Account) => Account(x.acctNum, x.balance, x.interestRate + adjustment) Try(updateAcct) }
Predicate might not be satisfied
![Page 71: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/71.jpg)
TrySimple pipelining onExample 1
case class Account(acctNum: Int, balance: Double, interestRate: Double)
val withdrawal = 1500val adjustment = 0.4val in = Try(getAcct)
val withdrawalResult = in map { (x: Account) => Account(x.acctNum, x.balance - withdrawal, x.interestRate) } filter { (x: Account) => x.balance > 12000 // acct in good standing } flatMap { (x: Account) => Account(x.acctNum, x.balance, x.interestRate + adjustment) Try(updateAcct) }
UPDATEACCT MIGHT FAIL
![Page 72: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/72.jpg)
TrySimple pipelining onExample 1
case class Account(acctNum: Int, balance: Double, interestRate: Double)
val withdrawal = 1500val adjustment = 0.4val in = Try(getAcct)
val withdrawalResult = in map { (x: Account) => Account(x.acctNum, x.balance - withdrawal, x.interestRate) } filter { (x: Account) => x.balance > 12000 // acct in good standing } flatMap { (x: Account) => Account(x.acctNum, x.balance, x.interestRate + adjustment) Try(updateAcct) }
Eliminates nested try blocksbut how can we handle these failures?
![Page 73: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/73.jpg)
TrySimple pipelining onExample 2
...by using recoverWith, recover, or orElse case class Tweet(from: String, retweets: Int)
val importantTweets = Try { server.getTweetList } orElse { cachedTweetList } map { twts => val avgRetweet = twts.map(_.retweets).reduce(_ + _) / twts.length (twts, avgRetweet) } filter { case (twts, avgRetweet) => twts.map(_.retweets).exists(_ > avgRetweet) } map { case (twts, avgRetweet) => twts.filter(_.retweets > avgRetweet) } recover { case nose: NoSuchElementException => // handle individually case usop: UnsupportedOperationException => // handle individually case other => // handle individually }
![Page 74: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/74.jpg)
Try&Futurescombining
case class Friend(name: String, age: String) val avgAge = Promise[Int]() val fut = future { // query a social network... List(Friend("Zoe", "25"), Friend("Jean", "27"), Friend("Paul", "3O")) } fut onComplete { tr => // compute average age of friends val result = tr map { friends => friends.map(_.age.toInt).reduce(_ + _) / friends.length } avgAge complete result } avgAge.future onComplete println
![Page 75: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/75.jpg)
Credits
PHILIPP HALLER
ALEX PROKOPEC
VOJIN JOVANOVIC
VIKTOR KLANG MARIUS ERIKSEN
HEATHER MILLER
ROLAND KUHN
DOUG LEA
TYPESAFE
TYPESAFE
EPFL
EPFL
EPFL
TYPESAFE
SUNY
HAVOC PENNINGTONTYPESAFE
![Page 76: futures - EPFLlampphaller/doc/Futures-Try-Sep2012.pdf · Java futures neither 2 efficient nor composable ... { // Thread 2 case x: Int => println ... => x.balance > 12000 // acct](https://reader031.vdocuments.us/reader031/viewer/2022021801/5b3a90697f8b9a560a8bb3f4/html5/thumbnails/76.jpg)
questions?http://docs.scala-lang.org/sips/pending/futures-promises.html