Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf ·...

34
Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development COMP4001 CSE UNSW Sydney Lecturer: John Potter

Transcript of Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf ·...

Page 1: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Introduction to Object Oriented / Functional

Programming 8

Object-Oriented Software Development

COMP4001 CSE UNSW Sydney

Lecturer: John Potter

Page 2: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Lecture Outline §  Actors Background §  Actors in Scala §  Examples §  Guidelines for Designing Actors

COMP4001 CSE UNSW Sydney 2

Page 3: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Concurrency on JVM §  Threads and locks (synchronized):

§  Error-prone code §  Data races and deadlocks §  Code is not composable §  Code extensions need to re-code synchronization

§  Correct solutions often don't scale §  Memory consumption problems §  Lock contention and bottlenecks

§  Debugging and testing is hard §  Hard to reproduce executions §  Non-deterministic behaviour

§  Shared memory model of concurrency COMP4001 CSE UNSW Sydney 3

Page 4: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Actors §  Actor model of computation

§  Introduced by Carl Hewitt in mid-70’s §  Popularized by Gul Agha in 80’s

§  Message-based concurrency model §  No shared memory

§  Most popular implementation: Erlang §  by Ericsson, who banned it internally in late 90’s! §  designed for telephony applications §  initial version implemented in Prolog

§  No widespread adoption in languages for standard VMs (e.g. JVM, .net) §  Until Scala, at least COMP4001 CSE UNSW Sydney 4

Page 5: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

The Actor Model §  Actors encapsulate their own state and behaviour

§  Like objects §  Actors should only use their "own" objects

§  Actors are active §  Like processes / threads / tasks §  Whereas objects are passive

COMP4001 CSE UNSW Sydney 5

Page 6: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Actor Communication §  Actors communicate via messages §  Messages are stored in mailboxes §  Messages are asynchronous

§  Non-blocking send §  Messages are sent and stored in the receiving actor’s mailbox

§  Blocking receive §  An actor selects and handles messages in its mailbox when it is

ready to do so

COMP4001 CSE UNSW Sydney 6

Page 7: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Schematic Form of an Actor

COMP4001 CSE UNSW Sydney 7

Page 8: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Outline §  Actors Background §  Actors in Scala §  Examples §  Guidelines for Designing Actors

COMP4001 CSE UNSW Sydney 8

Page 9: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Actors in Scala §  Lightweight concurrent processes

§  Actor model

§  Asynchronous message passing §  Expressive pattern matching

§  Unifies threads and events (efficient, scalable) §  Automatically mapped to multiple JVM threads

§  Implemented using fork-join framework in Java §  Many actors per thread.

§  May migrate via work-stealing implementation of fork-join §  Leverages multicore processors

§  No inversion of control §  Inversion of control can be a problem in event-based systems

COMP4001 CSE UNSW Sydney 9

Page 10: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Implementations §  Two major implementations §  Standard library scala.actors

§  as discussed in Programming in Scala §  http://www.scala-lang.org/docu/files/actors-api/actors_api_guide.html

§  Akka §  http://doc.akka.io/docs/akka/2.0/scala/actors.html

§  both Scala and Java libraries §  better supported and maintained

§  better support for distributed systems §  smooth integration between local and remote actors §  actors are created, and addressed, in a fixed hierarchy

COMP4001 CSE UNSW Sydney 10

Page 11: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Actors in scala.actors §  Implemented as an embedded DSL in a library §  Two principal operations (adopted from Erlang)

actor ! message // message send receive { // message receive case msgpat_1 => action_1 ... case msgpat_n => action_n

} §  Send ! is asynchronous

§  messages are buffered in actor's mailbox

§  Receive waits for message that matches any of the patterns msgpat_i COMP4001 CSE UNSW Sydney 11

Page 12: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Event Based Actors in Scala §  Do not consume a thread §  Very lightweight representation at runtime

§  Function object (similar to a Runnable)

§  Use react instead of receive for handling messages §  Restriction:

§  call to react does not return §  At end: exit or call rest of computation §  Shortcuts for sequence and looping

COMP4001 CSE UNSW Sydney 12

Page 13: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Scalability for multi-cores

COMP4001 CSE UNSW Sydney

§  Microbenchmarks run on 4 way dual core Opteron machine (8 cores total)

§  Compared to Doug Lea's FJTask framework for Java 13

Page 14: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

The lift Web Framework §  3rd party web framework §  Multithreaded, scalable §  Scala Actors used for critical parts

§  Session management (Session Actors) §  Dynamic content (Controller Actors)

§  Asynchronously, send updates to Page Actors §  Page Actor updates

§  packaged as DOM modifying JavaScript sent back to browser

§  Claimed to be more concise and simpler than Rails §  Automatically multi-threaded, which Rails is not.

COMP4001 CSE UNSW Sydney 14

Page 15: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Play §  a still lighter-weight modern web app framework

§  see http://www.playframework.org/

§  tutorial http://www.playframework.org/documentation/2.0/ScalaTodoList

§  Java and Scala §  stateless MVC architecture

§  like Ruby on Rails or Django

§  Scala-based templating framework §  http://www.playframework.org/documentation/2.0/ScalaTemplates §  FP helps here. Scala provides type safety

§  Also see http://www.typesafe.com/stack/ §  Scala compiler tools, AKKA actor framework, Play

COMP4001 CSESW Sydney 15

Page 16: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Outline §  Actors Background §  Actors in Scala §  Examples §  Guidelines for Designing Actors

COMP4001 CSE UNSW Sydney 16

Page 17: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

scala.actor Examples object Hamlet extends Actor {

def act() { for (i <- 1 to 5) { println("To be or not to be.") Thread.sleep(1000) } }

}

COMP4001 CSE UNSW Sydney 17

Page 18: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Actor Run as a Thread scala> Hamlet.start() To be or not to be. res3: scala.actors.Actor = Hamlet$@1689405 scala> To be or not to be. To be or not to be. To be or not to be. To be or not to be.

COMP4001 CSE UNSW Sydney

Note interleaving of interpreter thread and actor thread

Start actor thread

18

Page 19: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Factory Method: actor §  The actor method defines an Actor that

§  Executes actions defined in its block argument §  Starts immediately

scala> val ophelia = actor { | for (i <- 1 to 5) println("That is the question.") | Thread.sleep(1000) | } scala> That is the question. That is the question. That is the question. That is the question. That is the question.

COMP4001 CSE UNSW Sydney 19

Page 20: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Communicating actors val ghost = actor {

while (true) { receive { case msg => println("received message: " + msg) } }

} scala> ghost ! "hi there" received message: hi there

COMP4001 CSE UNSW Sydney

Select msg from actor’s mailbox

Message handler

Send message to actor

20

Page 21: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Lightweight Actors §  react instead of receive

§  an actor with a receive method consumes all of a thread’s stack that it is run on §  Because the actor continues after the receive block, possibly

using the value returned by the block §  The actor must be able to access any data stored on the call

stack for the thread, so that thread cannot be used by another actor (at least, not until the actor exits)

§  the alternative way of accepting messages is via the react method §  This has no return value §  So the call stack does not need to be preserved §  So the thread can be shared amongst different actors

COMP4001 CSE UNSW Sydney 21

Page 22: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Use of React §  react does not return a value, so the message

handler block you invoke it with must §  process that message §  arrange to do all of the actor’s remaining work.

§  A common way to do this is to have a single top-level method e.g. act() that models the top-level behaviour of the actor

§  If every actor uses react, then, in theory, only one thread is needed to run all actors §  In practice, some top-level actors may have dedicated

threads

COMP4001 CSE UNSW Sydney 22

Page 23: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Example of reactive actor object NameResolver extends Actor {

import java.net.{InetAddress, UnknownHostException} def act() { react { case (name: String, actor: Actor) => actor ! getip(name) act() case "EXIT" => println("Name resolver exiting.") // quit case msg => println("Unhandled message: " + msg) act() } }

} COMP4001 CSE UNSW Sydney 23

Page 24: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Use of Actor.loop §  The loop method allows a more readable version of

the above act() method §  With behaviour as defined above

§  except that "EXIT" is now another "Unhandled message" §  this actor continues forever

def act() { loop { react { case (name: String, actor: Actor) => actor ! getip(name) case msg => println("Unhandled message: " + msg) }

}

} COMP4001 CSE UNSW Sydney 24

Page 25: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Threads vs Actors §  The actor subsystem manages its own threads §  Client code do not need to explicitly manage these

threads §  Nor worry about how actors are mapped to threads

§  Every thread is usable as an actor via Actor.self §  Cannot use Thread.current which does not support Actor

methods §  Actor.self can be useful for debugging in the scala

interpreter §  See next example, based on NameResolver actor above

COMP4001 CSE UNSW Sydney 25

Page 26: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Use of Actor.self scala> NameResolver.start() res0: scala.actors.Actor = NameResolver$@90d6c5 scala> NameResolver ! ("www.scalalang.org", self) scala> self.receive { case x => x } res2: Any = Some(www.scalalang.org/128.178.154.102) scala> NameResolver ! ("wwwwww.scalalang.org", self) scala> self.receive { case x => x } res4: Any = None

COMP4001 CSE UNSW Sydney 26

Page 27: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Outline §  Actors Background §  Actors in Scala §  Examples §  Guidelines for Designing Actors

COMP4001 CSE UNSW Sydney 27

Page 28: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Guidelines for designing actors 1 §  Actors should not block

§  Unless they are sure not to handle any more requests §  In the worst case, deadlocks can arise

§  Instead of blocking actors should arrange to be sent a message when appropriate condition has been achieved

§  Example: instead of SleepingBeauty actor calling Thread.sleep, use a one-off helper:

actor { Thread.sleep(time) SleepingBeauty ! "WAKEUP"

}

COMP4001 CSE UNSW Sydney

Sleep is OK here because this actor never receives messages

Meanwhile SleepingBeauty can do other things 28

Page 29: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Example val hughGrant = actor {

def emoteLater() { val mainActor = self actor { Thread.sleep(1000) mainActor ! "Emote" } }

var emoted = 0 emoteLater() loop { react { case "Emote" => println("I'm acting!") emoted += 1 if (emoted < 5) emoteLater() case msg => println("Received: " + msg) } } }

COMP4001 CSE UNSW Sydney 29

Page 30: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Exercise §  Trace the behaviour of hughGrant

COMP4001 CSE UNSW Sydney 30

Page 31: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Guidelines for designing actors 2 §  Ensure that objects can only be accessed by one

actor at a time §  Otherwise there may be data races §  Shared data must be protected with locks

§  this will interfere with actor execution

§  Simplest strategy §  Only use immutable objects

§  More advanced strategy §  Allow objects to be “owned” by one actor at a time §  Either objects are encapsulated within an actor §  Or they may be transferred from one to another

§  the previous owner must not access the object after the transfer COMP4001 CSE UNSW Sydney 31

Page 32: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Guidelines for designing actors 3 §  Make messages self-contained §  Unlike synchronous method calls, reply messages

(if any) may not occur for some time after a request is sent §  So the receiver of the reply must be able to interpret what

request is being replied to §  Strategy 1: send the request (as an immutable object

reference) as part of the reply §  Strategy 2: use case classes to define different types of

messages to help identify potential request / reply pairs

COMP4001 CSE UNSW Sydney 32

Page 33: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Example: for NameResolver def act() { loop { react { case (name: String, actor: Actor) => actor ! (name, getip(name)) } } }

COMP4001 CSE UNSW Sydney

Request as part of Reply

Message includes Request and Respondee

33

Page 34: Introduction to Object Oriented / Functional Programming 8cs4001/12s1/lect/8.oofp.pdf · Introduction to Object Oriented / Functional Programming 8 Object-Oriented Software Development

Example case class LookupIP(name: String, respondto: Actor) case class LookupResult(name: String, address: Option[InetAddress]) def getip(name: String) = // as before val nameResolver2 = actor {

loop { react { case LookupIP(name, actor) => actor ! LookupResult(name, getip(name)) } }

}

COMP4001 CSE UNSW Sydney 34