futures, actors, and streamsstg-tud.github.io/ctbd/2016/ctbd_09_futures_actors.pdf · futures,...

153
Concepts and Technologies for Distributed Systems and Big Data Processing Philipp Haller KTH Royal Institute of Technology Sweden TU Darmstadt, Germany, 24 May 2016 Futures, Actors, and Streams

Upload: others

Post on 22-May-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Concepts and Technologiesfor

Distributed Systems and Big Data Processing

Philipp HallerKTH Royal Institute of Technology

Sweden

TU Darmstadt, Germany, 24 May 2016

Futures, Actors, and Streams

Page 2: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Programming a Concurrent World

• How to compose programs handling

• asynchronous events?

• streams of asynchronous events?

• distributed events?

➟ Programming abstractions for concurrency!

2

Page 3: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Overview

• Futures, promises

• Async/await

• Actors

3

Page 4: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

4

Page 5: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

Page 6: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

Page 7: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

Page 8: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

Page 9: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

Page 10: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

Page 11: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

• Join-calculus

Page 12: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

• Join-calculus

• Reactive streams

Page 13: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

• Join-calculus

• Reactive streams

• CSP

Page 14: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

• Join-calculus

• Reactive streams

• CSP

• Async CML

Page 15: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

• Join-calculus

• Reactive streams

• CSP

• Async CML

• …

Page 16: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why a Growable Language for Concurrency?

• Concurrency not a solved problem ➟ development of new programming models

4

• Futures, promises

• async/await

• STM

• Agents

• Actors

• Join-calculus

• Reactive streams

• CSP

• Async CML

• …Which one is going to “win”?

Page 17: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Background

5

Page 18: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Background

• Authored or co-authored:

• Scala Actors (2006)

• Scala futures and promises (2011/2012)

• Scala Async (2013)

5

Page 19: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Background

• Authored or co-authored:

• Scala Actors (2006)

• Scala futures and promises (2011/2012)

• Scala Async (2013)

• Contributed to Akka (Typesafe/Lightbend)

5

Page 20: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Background

• Authored or co-authored:

• Scala Actors (2006)

• Scala futures and promises (2011/2012)

• Scala Async (2013)

• Contributed to Akka (Typesafe/Lightbend)

• Akka.js project (2014)

5

Page 21: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Background

• Authored or co-authored:

• Scala Actors (2006)

• Scala futures and promises (2011/2012)

• Scala Async (2013)

• Contributed to Akka (Typesafe/Lightbend)

• Akka.js project (2014)

5

Other proposals and research projects:

• Scala Joins (2008)

• FlowPools (2012)

• Spores (safer closures)

• Capabilities and uniqueness

• …

Page 22: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

6

Page 23: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

6

Page 24: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

• Functions:

6

Page 25: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

• Functions:

• { param => fun(param) }

6

Page 26: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

• Functions:

• { param => fun(param) }

• (param: T) => fun(param)

6

Page 27: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

• Functions:

• { param => fun(param) }

• (param: T) => fun(param)

• Function type: T => S or (T, S) => U

6

Page 28: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

• Functions:

• { param => fun(param) }

• (param: T) => fun(param)

• Function type: T => S or (T, S) => U

• Methods: def meth(x: T, y: S): R = { .. }

6

Page 29: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer

• Local variables: val x = fun(arg) // type inference

• Functions:

• { param => fun(param) }

• (param: T) => fun(param)

• Function type: T => S or (T, S) => U

• Methods: def meth(x: T, y: S): R = { .. }

• Classes: class C extends D { .. }

6

Page 30: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

Page 31: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

• Generics:

Page 32: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

• Generics:

• class C[T] { var fld: T = _ ; .. }

Page 33: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

• Generics:

• class C[T] { var fld: T = _ ; .. }

• def convert[T](obj: T): Result = ..

Page 34: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

• Generics:

• class C[T] { var fld: T = _ ; .. }

• def convert[T](obj: T): Result = ..

• Pattern matching:

Page 35: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

• Generics:

• class C[T] { var fld: T = _ ; .. }

• def convert[T](obj: T): Result = ..

• Pattern matching:

• case class Person(name: String, age: Int)

Page 36: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Scala Primer (2)

7

• Generics:

• class C[T] { var fld: T = _ ; .. }

• def convert[T](obj: T): Result = ..

• Pattern matching:

• case class Person(name: String, age: Int)

• val isAdult = p match { case Person(_, a) => a >= 18 case Alien(_, _) => false }

Page 37: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

• Common task:

• Convert object to JSON

• Send HTTP request containing JSON

8

Page 38: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

• Common task:

• Convert object to JSON

• Send HTTP request containing JSON

8

import scala.util.parsing.json._

def convert[T](obj: T): Future[JSONType] def sendReq(json: JSONType): Future[JSONType]

Page 39: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

• Common task:

• Convert object to JSON

• Send HTTP request containing JSON

8

import scala.util.parsing.json._

def convert[T](obj: T): Future[JSONType] def sendReq(json: JSONType): Future[JSONType]

Page 40: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

• Common task:

• Convert object to JSON

• Send HTTP request containing JSON

8

import scala.util.parsing.json._

def convert[T](obj: T): Future[JSONType] def sendReq(json: JSONType): Future[JSONType]

Ousterhout et al. Making sense of performance in data analytics frameworks. NSDI ’15

Page 41: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Callbacks

• How to respond to asynchronous completion event?

➟ Register callback

9

Page 42: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Callbacks

• How to respond to asynchronous completion event?

➟ Register callback

9

val person = Person(“Tim”, 25)

val fut: Future[JSONType] = convert(person)

fut.foreach { json => val resp: Future[JSONType] = sendReq(json) .. }

Page 43: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Exceptions

• Serialization to JSON may fail at runtime

• Closure passed to foreach not executed in this case

• How to handle asynchronous exceptions?

10

Page 44: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Exceptions

• Serialization to JSON may fail at runtime

• Closure passed to foreach not executed in this case

• How to handle asynchronous exceptions?

10

val fut: Future[JSONType] = convert(person)

fut.onComplete { case Success(json) => val resp: Future[JSONType] = sendReq(json) case Failure(e) => e.printStackTrace() }

Page 45: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Partial Functions

11

{ case Success(json) => .. case Failure(e) => .. }

Page 46: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Partial Functions

11

{ case Success(json) => .. case Failure(e) => .. }

… creates an instance of PartialFunction[T, R]:

Page 47: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Partial Functions

11

{ case Success(json) => .. case Failure(e) => .. }

… creates an instance of PartialFunction[T, R]:

val pf: PartialFunction[Try[JSONType], Any] = { case Success(json) => .. case Failure(e) => .. }

Page 48: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Type of Partial Functions

• Partial functions have a type PartialFunction[A, B]

• PartialFunction[A, B] is a subtype of Function1[A, B]

12

Page 49: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Type of Partial Functions

• Partial functions have a type PartialFunction[A, B]

• PartialFunction[A, B] is a subtype of Function1[A, B]

12

abstract class Function1[A, B] { def apply(x: A): B .. }

abstract class PartialFunction[A, B] extends Function1[A, B] { def isDefinedAt(x: A): Boolean def orElse[A1 <: A, B1 >: B] (that: PartialFunction[A1, B1]): PartialFunction[A1, B1] .. }

Page 50: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Type of Partial Functions

• Partial functions have a type PartialFunction[A, B]

• PartialFunction[A, B] is a subtype of Function1[A, B]

12

abstract class Function1[A, B] { def apply(x: A): B .. }

abstract class PartialFunction[A, B] extends Function1[A, B] { def isDefinedAt(x: A): Boolean def orElse[A1 <: A, B1 >: B] (that: PartialFunction[A1, B1]): PartialFunction[A1, B1] .. }

Simplified!

Page 51: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Success and Failure

13

package scala.util

abstract class Try[+T]

case class Success[+T](v: T) extends Try[T]

case class Failure[+T](e: Throwable) extends Try[T]

Page 52: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Nested Exceptions

➟ Exception handling tedious and not compositional:

14

Page 53: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Nested Exceptions

➟ Exception handling tedious and not compositional:

14

val fut: Future[JSONType] = convert(person)

fut.onComplete { case Success(json) => val resp: Future[JSONType] = sendReq(json) resp.onComplete { case Success(jsonResp) => .. // happy path case Failure(e1) => e1.printStackTrace(); ??? } case Failure(e2) => e2.printStackTrace(); ??? }

Page 54: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Failed Futures

15

Page 55: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Failed Futures

• Future[T] is completed with Try[T], i.e., with success or failure

15

Page 56: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Failed Futures

• Future[T] is completed with Try[T], i.e., with success or failure

• Combinators enable compositional failure handling

15

Page 57: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Failed Futures

• Future[T] is completed with Try[T], i.e., with success or failure

• Combinators enable compositional failure handling

• Example:

15

Page 58: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Failed Futures

• Future[T] is completed with Try[T], i.e., with success or failure

• Combinators enable compositional failure handling

• Example:

15

val resp: Future[JSONType] = sendReq(json) val processed = resp.map { jsonResp => .. // happy path }

Page 59: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Failed Futures

• Future[T] is completed with Try[T], i.e., with success or failure

• Combinators enable compositional failure handling

• Example:

15

val resp: Future[JSONType] = sendReq(json) val processed = resp.map { jsonResp => .. // happy path }

Encapsulates failure

Page 60: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Map Combinator

16

Page 61: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Map Combinator• Creates a new future by applying a function to the

successful result of the receiver future

16

Page 62: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Map Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• If the function application results in an uncaught exception e then the new future is completed with e

16

Page 63: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Map Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• If the function application results in an uncaught exception e then the new future is completed with e

• If the receiver future is completed with an exception e then the new, pending future is also completed with e

16

Page 64: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Map Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• If the function application results in an uncaught exception e then the new future is completed with e

• If the receiver future is completed with an exception e then the new, pending future is also completed with e

16

abstract class Future[+T] extends Awaitable[T] {

def map[S](f: T => S)(implicit ..): Future[S]

// .. }

Page 65: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Future Composition

17

val fut: Future[JSONType] = convert(person)

val processed = fut.map { json => val resp: Future[JSONType] = sendReq(json) resp.map { jsonResp => .. // happy path } }

Page 66: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Future Composition

17

val fut: Future[JSONType] = convert(person)

val processed = fut.map { json => val resp: Future[JSONType] = sendReq(json) resp.map { jsonResp => .. // happy path } }

Encapsulates all failures

Page 67: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Future Composition

17

val fut: Future[JSONType] = convert(person)

val processed = fut.map { json => val resp: Future[JSONType] = sendReq(json) resp.map { jsonResp => .. // happy path } }

Encapsulates all failures

Problem: processed has type

Future[Future[T]]

Page 68: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Future Pipelining

18

val fut: Future[JSONType] = convert(person)

val processed = fut.flatMap { json => val resp: Future[JSONType] = sendReq(json) resp.map { jsonResp => .. // happy path } }

Page 69: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Future Pipelining

18

val fut: Future[JSONType] = convert(person)

val processed = fut.flatMap { json => val resp: Future[JSONType] = sendReq(json) resp.map { jsonResp => .. // happy path } }

Page 70: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Future Pipelining

Future pipelining: the result of the inner future (result of

map) determines the result of the outer future (processed)

18

val fut: Future[JSONType] = convert(person)

val processed = fut.flatMap { json => val resp: Future[JSONType] = sendReq(json) resp.map { jsonResp => .. // happy path } }

Page 71: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

FlatMap Combinator

19

Page 72: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

FlatMap Combinator• Creates a new future by applying a function to the

successful result of the receiver future

19

Page 73: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

FlatMap Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• The future result of the function application determines the result of the new future

19

Page 74: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

FlatMap Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• The future result of the function application determines the result of the new future

• If the function application results in an uncaught exception e then the new future is completed with e

19

Page 75: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

FlatMap Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• The future result of the function application determines the result of the new future

• If the function application results in an uncaught exception e then the new future is completed with e

• If the receiver future is completed with an exception e then the new, pending future is also completed with e

19

Page 76: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

FlatMap Combinator• Creates a new future by applying a function to the

successful result of the receiver future

• The future result of the function application determines the result of the new future

• If the function application results in an uncaught exception e then the new future is completed with e

• If the receiver future is completed with an exception e then the new, pending future is also completed with e

19

def flatMap[S](f: T => Future[S])(implicit ..): Future[S]

Page 77: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures

20

Page 78: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures• Futures are created based on (a) computations, (b) events,

or (c) combinations thereof

20

Page 79: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures• Futures are created based on (a) computations, (b) events,

or (c) combinations thereof

• Creating computation-based futures:

20

object Future {

def apply[T](body: => T)(implicit ..): Future[T]

}

Page 80: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures• Futures are created based on (a) computations, (b) events,

or (c) combinations thereof

• Creating computation-based futures:

20

object Future {

def apply[T](body: => T)(implicit ..): Future[T]

}Singleton object

Page 81: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures• Futures are created based on (a) computations, (b) events,

or (c) combinations thereof

• Creating computation-based futures:

20

object Future {

def apply[T](body: => T)(implicit ..): Future[T]

}Singleton object

“Code block” with result type T

Page 82: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures• Futures are created based on (a) computations, (b) events,

or (c) combinations thereof

• Creating computation-based futures:

20

object Future {

def apply[T](body: => T)(implicit ..): Future[T]

}Singleton object

“Code block” with result type T

“Unrelated” to the singleton

object!

Page 83: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Futures: Example

21

Page 84: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Futures: Example

21

val firstGoodDeal = Future { usedCars.find(car => isGoodDeal(car)) }

Page 85: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Futures: Example

21

val firstGoodDeal = Future { usedCars.find(car => isGoodDeal(car)) }

val firstGoodDeal = Future.apply({ usedCars.find(car => isGoodDeal(car)) })

Short syntax for:

Page 86: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Futures: Example

21

val firstGoodDeal = Future { usedCars.find(car => isGoodDeal(car)) }

val firstGoodDeal = Future.apply({ usedCars.find(car => isGoodDeal(car)) })

Short syntax for:

Type inference:val firstGoodDeal = Future.apply[Option[Car]]({ usedCars.find(car => isGoodDeal(car)) })

Page 87: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Futures: Example

21

val firstGoodDeal = Future { usedCars.find(car => isGoodDeal(car)) }

val firstGoodDeal = Future.apply({ usedCars.find(car => isGoodDeal(car)) })

Short syntax for:

Type inference:val firstGoodDeal = Future.apply[Option[Car]]({ usedCars.find(car => isGoodDeal(car)) })

Type Future[Option[Car]]

Page 88: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures: Operationally

22

Page 89: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures: Operationally• Invoking the shown factory method creates a task object

encapsulating the computation

22

Page 90: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures: Operationally• Invoking the shown factory method creates a task object

encapsulating the computation

• The task object is scheduled for execution by an execution context

22

Page 91: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures: Operationally• Invoking the shown factory method creates a task object

encapsulating the computation

• The task object is scheduled for execution by an execution context

• An execution context is an object capable of executing tasks, typically using a thread pool

22

Page 92: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Creating Futures: Operationally• Invoking the shown factory method creates a task object

encapsulating the computation

• The task object is scheduled for execution by an execution context

• An execution context is an object capable of executing tasks, typically using a thread pool

• Future tasks are submitted to the current implicit execution context

22

def apply[T](body: => T)(implicit executor: ExecutionContext): Future[T]

Page 93: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Implicit Execution ContextsImplicit parameter requires selecting a execution context

23

Page 94: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Implicit Execution ContextsImplicit parameter requires selecting a execution context

23

Welcome to Scala version 2.11.6 (Java HotSpot(TM) ..). Type in expressions to have them evaluated. Type :help for more information.

scala> import scala.concurrent._ import scala.concurrent._

scala> val fut = Future { 40 + 2 }

Page 95: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Implicit Execution ContextsImplicit parameter requires selecting a execution context

23

<console>:10: error: Cannot find an implicit ExecutionContext. You might pass

Welcome to Scala version 2.11.6 (Java HotSpot(TM) ..). Type in expressions to have them evaluated. Type :help for more information.

scala> import scala.concurrent._ import scala.concurrent._

scala> val fut = Future { 40 + 2 }

Page 96: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Implicit Execution ContextsImplicit parameter requires selecting a execution context

23

???

<console>:10: error: Cannot find an implicit ExecutionContext. You might pass

Welcome to Scala version 2.11.6 (Java HotSpot(TM) ..). Type in expressions to have them evaluated. Type :help for more information.

scala> import scala.concurrent._ import scala.concurrent._

scala> val fut = Future { 40 + 2 }

Page 97: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Implicit Execution ContextsImplicit parameter requires selecting a execution context

23

<console>:10: error: Cannot find an implicit ExecutionContext. You might pass

Welcome to Scala version 2.11.6 (Java HotSpot(TM) ..). Type in expressions to have them evaluated. Type :help for more information.

scala> import scala.concurrent._ import scala.concurrent._

scala> val fut = Future { 40 + 2 } But…

Page 98: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Implicit Execution ContextsImplicit parameter requires selecting a execution context

23

an (implicit ec: ExecutionContext) parameter to your method or import scala.concurrent.ExecutionContext.Implicits.global. val fut = Future { 40 + 2 } ^

<console>:10: error: Cannot find an implicit ExecutionContext. You might pass

Welcome to Scala version 2.11.6 (Java HotSpot(TM) ..). Type in expressions to have them evaluated. Type :help for more information.

scala> import scala.concurrent._ import scala.concurrent._

scala> val fut = Future { 40 + 2 }

Page 99: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Promise

24

Page 100: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Promise

Main purpose: create futures for non-lexically-scoped asynchronous code

24

Page 101: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Promise

Main purpose: create futures for non-lexically-scoped asynchronous code

24

Example

Function for creating a Future that is completed with value after delay milliseconds

Page 102: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Promise

Main purpose: create futures for non-lexically-scoped asynchronous code

24

def after[T](delay: Long, value: T): Future[T]

Example

Function for creating a Future that is completed with value after delay milliseconds

Page 103: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 1

25

def after1[T](delay: Long, value: T) = Future { Thread.sleep(delay) value }

Page 104: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 1

26

How does it behave?

Page 105: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 1

26

assert(Runtime.getRuntime() .availableProcessors() == 8)

for (_ <- 1 to 8) yield after1(1000, true)

val later = after1(1000, true)

How does it behave?

Page 106: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 1

26

assert(Runtime.getRuntime() .availableProcessors() == 8)

for (_ <- 1 to 8) yield after1(1000, true)

val later = after1(1000, true)

How does it behave?

Quiz: when is “later” completed?

Page 107: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 1

26

assert(Runtime.getRuntime() .availableProcessors() == 8)

for (_ <- 1 to 8) yield after1(1000, true)

val later = after1(1000, true)

How does it behave?

Quiz: when is “later” completed?

Answer: after either ~1 s or ~2 s (most often)

Page 108: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Promise

27

object Promise { def apply[T](): Promise[T] }

Page 109: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Promise

27

object Promise { def apply[T](): Promise[T] }

trait Promise[T] { def success(value: T): Promise[T] def failure(cause: Throwable): Promise[T]

def future: Future[T] }

Page 110: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 2

28

def after2[T](delay: Long, value: T) = { val promise = Promise[T]() timer.schedule(new TimerTask { def run(): Unit = promise.success(value) }, delay) promise.future }

Page 111: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

“after”, Version 2

28

def after2[T](delay: Long, value: T) = { val promise = Promise[T]() timer.schedule(new TimerTask { def run(): Unit = promise.success(value) }, delay) promise.future }

Much better behaved!

Page 112: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

What is Async?

• Scala module

• "org.scala-lang.modules" %% "scala-async"

• Purpose: simplify programming with futures

• Scala Improvement Proposal SIP-22

• Releases for Scala 2.10 and 2.11

29

Page 113: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

What Async Provides

• Future and Promise provide types and operations for managing data flow

• Very little support for control flow

• Async complements Future and Promise with constructs to manage control flow

30

Page 114: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Programming Model

Basis: suspendible computations

31

Page 115: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Programming Model

Basis: suspendible computations

• async { .. } — delimit suspendible computation

31

Page 116: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Programming Model

Basis: suspendible computations

• async { .. } — delimit suspendible computation

• await(future) — suspend computation until

future is completed

31

Page 117: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Async

32

Page 118: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Async

32

object Async {

def async[T](body: => T): Future[T]

def await[T](future: Future[T]): T

}

Page 119: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

33

val fstGoodDeal: Future[Option[Car]] = .. val sndGoodDeal: Future[Option[Car]] = ..

val goodCar = async { val car1 = await(fstGoodDeal).get val car2 = await(sndGoodDeal).get if (car1.price < car2.price) car1 else car2 }

Page 120: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Futures vs. Async

• “Futures and Async: When to Use Which?”, Scala Days 2014, Berlin

• Video:

34

https://www.parleys.com/tutorial/futures-async-when-use-which

Page 121: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Async in Other Languages

Constructs similar to async/await are found in a number of widely-used languages:

• C#

• Dart (Google)

• Hack (Facebook)

• ECMAScript 7 1

35

1 http://tc39.github.io/ecmascript-asyncawait/

Page 122: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

From Futures to Actors

• Limitations of futures:

• At most one completion event per future

• Overhead when creating many futures

• How to model distributed systems?

36

Page 123: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model

37

Page 124: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model• Model of concurrent computation whose universal primitive is

the “actor” [Hewitt et al. ’73]

37

Page 125: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model• Model of concurrent computation whose universal primitive is

the “actor” [Hewitt et al. ’73]

• Actors = concurrent “processes” communicating via asynchronous messages

37

Page 126: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model• Model of concurrent computation whose universal primitive is

the “actor” [Hewitt et al. ’73]

• Actors = concurrent “processes” communicating via asynchronous messages

37

Related to active objects

Page 127: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model• Model of concurrent computation whose universal primitive is

the “actor” [Hewitt et al. ’73]

• Actors = concurrent “processes” communicating via asynchronous messages

• Upon reception of a message, an actor may

• change its behavior/state

• send messages to actors (including itself)

• create new actors

37

Related to active objects

Page 128: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model• Model of concurrent computation whose universal primitive is

the “actor” [Hewitt et al. ’73]

• Actors = concurrent “processes” communicating via asynchronous messages

• Upon reception of a message, an actor may

• change its behavior/state

• send messages to actors (including itself)

• create new actors

• Fair scheduling

37

Related to active objects

Page 129: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

The Actor Model• Model of concurrent computation whose universal primitive is

the “actor” [Hewitt et al. ’73]

• Actors = concurrent “processes” communicating via asynchronous messages

• Upon reception of a message, an actor may

• change its behavior/state

• send messages to actors (including itself)

• create new actors

• Fair scheduling

• Decoupling: message sender cannot fail due to receiver

37

Related to active objects

Page 130: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

38

class ActorWithTasks(tasks: ...) extends Actor { ...

def receive = { case TaskFor(workers) => val from = sender

val requests = (tasks zip workers).map { case (task, worker) => worker ? task } val allDone = Future.sequence(requests) allDone andThen { seq => from ! seq.mkString(",") } } }

Page 131: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Example

38

class ActorWithTasks(tasks: ...) extends Actor { ...

def receive = { case TaskFor(workers) => val from = sender

val requests = (tasks zip workers).map { case (task, worker) => worker ? task } val allDone = Future.sequence(requests) allDone andThen { seq => from ! seq.mkString(",") } } } Using Akka (http://akka.io/)

Page 132: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Anatomy of an Actor (1)• An actor is an active object with its own behavior

• Actor behavior defined by:

• subclassing Actor

• implementing def receive

39

class ActorWithTasks(tasks: List[Task]) extends Actor { def receive = { case TaskFor(workers) => // send `tasks` to `workers` case Stop => // stop `self` } }

Page 133: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Anatomy of an Actor (2)• Exchanged messages should be immutable

• And serializable, to enable remote messaging

• Message types should implement structural equality

• In Scala: case classes and case objects

• Enables pattern matching on the receiver side

40

case class TaskFor(workers: List[ActorRef]) case object Stop

Page 134: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Anatomy of an Actor (3)• Actors are isolated

• Strong encapsulation of state

• Requires restricting access and creation

• Separate Actor instance and ActorRef

• ActorRef public, safe interface to actor

41

val system = ActorSystem(“test-system”) val actor1: ActorRef = system.actorOf[ActorWithTasks]

actor1 ! TaskFor(List()) // async message send

Page 135: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?

42

Page 136: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?Reason 1: simplified concurrency

42

Page 137: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?Reason 1: simplified concurrency

• “Share nothing”: strong isolation of actors ➟ no race conditions

42

Page 138: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?Reason 1: simplified concurrency

• “Share nothing”: strong isolation of actors ➟ no race conditions

• Actors handle at most one message at a time ➟ sequential reasoning

42

Page 139: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?Reason 1: simplified concurrency

• “Share nothing”: strong isolation of actors ➟ no race conditions

• Actors handle at most one message at a time ➟ sequential reasoning

42

“Macro-step semantics”

Page 140: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?Reason 1: simplified concurrency

• “Share nothing”: strong isolation of actors ➟ no race conditions

• Actors handle at most one message at a time ➟ sequential reasoning

• Asynchronous message handling ➟ less risk of deadlocks

42

“Macro-step semantics”

Page 141: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors?Reason 1: simplified concurrency

• “Share nothing”: strong isolation of actors ➟ no race conditions

• Actors handle at most one message at a time ➟ sequential reasoning

• Asynchronous message handling ➟ less risk of deadlocks

• No “inversion of control”: access to own state and messages in safe, direct way

42

“Macro-step semantics”

Page 142: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)

43

Page 143: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)Reason 2: actors model reality of distributed systems

43

Page 144: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)Reason 2: actors model reality of distributed systems

• Message sends truly asynchronous

43

Page 145: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)Reason 2: actors model reality of distributed systems

• Message sends truly asynchronous

• Message reception not guaranteed

43

Page 146: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)Reason 2: actors model reality of distributed systems

• Message sends truly asynchronous

• Message reception not guaranteed

• Non-deterministic message ordering

43

Page 147: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)Reason 2: actors model reality of distributed systems

• Message sends truly asynchronous

• Message reception not guaranteed

• Non-deterministic message ordering

• Some implementations preserve message ordering between pairs of actors

43

Page 148: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Why Actors? (cont’d)Reason 2: actors model reality of distributed systems

• Message sends truly asynchronous

• Message reception not guaranteed

• Non-deterministic message ordering

• Some implementations preserve message ordering between pairs of actors

Therefore, actors well-suited as a foundation for distributed systems

43

Page 149: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Summary

44

Page 150: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Summary

• Concurrency benefits from growable languages

44

Page 151: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Summary

• Concurrency benefits from growable languages

• Futures and promises a versatile abstraction for single, asynchronous events

44

Page 152: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Summary

• Concurrency benefits from growable languages

• Futures and promises a versatile abstraction for single, asynchronous events

• Supported by async/await

44

Page 153: Futures, Actors, and Streamsstg-tud.github.io/ctbd/2016/CTBD_09_futures_actors.pdf · Futures, Actors, and Streams. Philipp Haller Programming a Concurrent World ... • Contributed

Philipp Haller

Summary

• Concurrency benefits from growable languages

• Futures and promises a versatile abstraction for single, asynchronous events

• Supported by async/await

• The actor model faithfully models distributed systems

44