28.04.2014 Views

Scala Actors

Scala Actors

Scala Actors

SHOW MORE
SHOW LESS

Transform your PDFs into Flipbooks and boost your revenue!

Leverage SEO-optimized Flipbooks, powerful backlinks, and multimedia content to professionally showcase your products and significantly increase your reach.

<strong>Scala</strong> <strong>Actors</strong> <br />

Concurrency is an important topic in computer science. Advances in computer <br />

architecture continue to push for greater levels of thread-­‐level parallelism. Moving <br />

forward, computer languages must be able to efficiently and effectively implement <br />

concurrency to remain viable. <br />

Traditionally, concurrency can be handled using task-­‐based threads or event-­‐based <br />

threads. Task-­‐based threading, as used by java, involves defining a ‘task’ to run as a <br />

thread. To run a task-­‐based thread, a new thread is created and started to complete <br />

the task and can then run in parallel to any other processing. When the thread has <br />

completed its task, it is discarded. <br />

Alternatively, <strong>Scala</strong> implements concurrency using event-­‐based actors. The name <br />

actor can is telling of what an actor does. In performing arts, an actor is an <br />

individual that has a role to perform and they can communicate with other actors by <br />

communicating. Similarly, actors in <strong>Scala</strong> are objects that run concurrent processes <br />

and can send and receive messages from other actors. Messages passed to an actor <br />

are queue in the actor’s mailbox. Typically, an actor will perform pattern matching <br />

on the message to determine what actions to take on the message. <br />

The actor paradigm is considered to be easy to understand for the developer. <br />

Additionally, the functional programming that is available to the <strong>Scala</strong> programmer <br />

can improve the code design for concurrency by minimizing mutable state. <br />

An example <br />

Consider the following example. A familiar game played by kids is Marco Polo. In <br />

this game, a player will call out “Marco”, to which a second player must respond <br />

“Polo”. We can recreate this behavior using <strong>Scala</strong> and actors. <br />

To be able to use actors, the following <strong>Scala</strong> libraries must be imported into the <br />

application. <br />

import scala.actors._<br />

import scala.actors.Actor._<br />

The package scala.actors includes the trait Actor that can be extend to create the <br />

actor objects as well as all other classes, objects and traits related to actors. The <br />

package scala.actors.Actor has methods that are used by the actor objects. <br />

Next, define singleton objects to act as messages. These objects are declared to be <br />

case objects as the receiving actor will use pattern matching to determine the action <br />

to take. <br />

<br />

1


case object Marco<br />

case object Polo<br />

case object Stop<br />

Next, define the behavior of the player1 object with the class ‘Marco’. <br />

class Marco(count: Int, player2: Actor) extends Actor {<br />

def act() {<br />

var tries = count - 1<br />

player2 ! Marco<br />

println("Marco...")<br />

while (true) {<br />

receive {<br />

case Polo => {<br />

if (tries > 1) {<br />

println("Marco...")<br />

player2 ! Marco<br />

tries -= 1<br />

} else {<br />

player2 ! Stop<br />

exit()<br />

}<br />

}<br />

}<br />

}<br />

}<br />

}<br />

The <strong>Actors</strong> ‘act’ method is used to define the behavior of the Actor. A variable ‘tries’ <br />

is defined to limit the number of messages sent. Player1 initiates the game by <br />

sending player2 the message ‘Marco’. In <strong>Scala</strong>, messages are sent to actors using the <br />

‘!’ operator. Next, player1 continuously waits for the return ‘Polo’ message using the <br />

‘receive’ method and pattern matching. Upon receiving the ‘Polo’ message, player1 <br />

will again send the ‘Marco’ message to player2 if the maximum number of tries has <br />

not been reached. Once the number of tries has been reached, the actor exits. <br />

Next, the behavior of player2 is defined with the class ‘Polo’. <br />

class Polo extends Actor {<br />

def act() {<br />

while (true) {<br />

receive {<br />

<br />

2


case Marco => {<br />

println("Polo...")<br />

sender ! Polo<br />

}<br />

case Stop => {<br />

exit()<br />

}<br />

}<br />

}<br />

}<br />

}<br />

The player2 object, implementing the ‘Polo’ class, waits in a loop to receive the <br />

‘Marco’ message from player 1. Every time the actor receives the ‘Marco’ message, it <br />

returns the ‘Polo’ message. Notice that the ‘Polo’ message is sent to the ‘sender’ as <br />

opposed to explicitly sending the message player1. Sender refers to the actor that <br />

sent the last received message. <br />

Lastly, an object is defined that creates instances of the classes we created and starts <br />

the actors. <br />

object marcopolo extends Application {<br />

val player2 = new Polo()<br />

val player1 = new Marco(10, player2)<br />

player1.start()<br />

player2.start()<br />

}<br />

The following is the output of the compiling and running the previously described <br />

function: <br />

$ scalac marcopolo.scala<br />

$ scala marcopolo<br />

Polo...<br />

Marco...<br />

Polo...<br />

Marco...<br />

Polo...<br />

Marco...<br />

Polo...<br />

Marco...<br />

Polo...<br />

<br />

3


Marco...<br />

Polo...<br />

Marco...<br />

Polo...<br />

Marco...<br />

Polo...<br />

Marco...<br />

Polo...<br />

act() method vs. actor{} function <br />

In the previous example, we defined an actor’s ‘act’ method to define the behavior of <br />

the actor. However, there is a second method to create an actor without creating a <br />

class using the ‘actor’ function. For example, the ‘player2’ could be redefined to the <br />

following: <br />

val player2: Actor = actor {<br />

while (true) {<br />

receieve {<br />

case Marco => {<br />

println("Polo...")<br />

sender ! Polo<br />

}<br />

case Stop => {<br />

exit()<br />

}<br />

}<br />

}<br />

}<br />

Here, the player2 actor is defined inline as opposed to instantiating an Actor class. It <br />

is important to note that using this method, it is no longer necessary to class the <br />

‘start’ method of the actor object. The actor is started immediately. <br />

receive{} function vs. react{} function <br />

In the previous example, we waited to for a message to return using the ‘receive’ <br />

function. The ‘receive’ function is a blocking function, meaning that the thread that <br />

is currently executing the thread will be blocked until the message is received. <br />

Using the receive message preserves the call stack. <br />

<br />

4


In <strong>Scala</strong>, actors are executed on a thread pool that initially has 4 worker threads. <br />

When the number of blocking threads increases, the size of the thread pool grows to <br />

match. However, in situations with a large number of actors, it may be desirable to <br />

avoid this blocking behavior. <br />

<strong>Scala</strong> has a second method to return a message: the ‘react’ function. As opposed to <br />

the ‘receive’ function, the ‘react’ function is non-­‐blocking. Instead of waiting for the <br />

message to return, ‘react’ creates a closure. When the react function receives a <br />

value, an available thread begins execution the actor. Take note, however, that the <br />

react function cannot be used inside a while loop. As a result, <strong>Scala</strong> includes a ‘loop’ <br />

function to that behaves as an infinite loop and ‘loopWhile’ that behaves in a similar <br />

manner to a while loop. Using the ‘react’ function instead of the ‘receive’ function <br />

could be written as follows: <br />

class Polo extends Actor {<br />

def act() {<br />

loop {<br />

react {<br />

case Marco => {<br />

println("Polo...")<br />

sender ! Polo<br />

}<br />

case Stop => {<br />

exit()<br />

}<br />

}<br />

}<br />

}<br />

}<br />

In addition to the ‘react’ and ‘receive’ functions, <strong>Scala</strong> also includes ‘reactWithin’ and <br />

‘receiveWithin’ functions. These functions work in the same way as the <br />

corresponding ‘react’ and ‘receive’ functions but allow the programmer to specify a <br />

timeout. <br />

!, !!, and !? <br />

In the previous example, messages were sent using the ‘!’ operator. <strong>Scala</strong> also <br />

provides the ‘!?’ operator which will create a synchronous message. Instead of <br />

returning like an asynchronous message, this operator waits for a reply. For <br />

example the following code: <br />

var response = player1 !? Polo<br />

<br />

5


This code will send the Polo message to the object player1 and wait for a response, <br />

which it will assign to the variable ‘response’. <br />

Additionally, <strong>Scala</strong> has the ‘!!’ operator, which returns immediately. However, since <br />

a message has not been received back, the operator returns a future instead. A <br />

future is a representation of the response that allows to the caller to await the reply. <br />

In this case, the blocking will occur only when trying to access the future. <br />

This tutorial has presented a brief introduction to <strong>Scala</strong> actors. These concepts can <br />

be extended to create far more complex and interesting code. The <strong>Scala</strong> distribution <br />

includes a several examples of the use of <strong>Scala</strong> actors. These are available at /doc/scala-­‐devel-­‐docs/examples/actors/. <br />

<br />

6


References <br />

Tate, Bruce A. Seven Languages in Seven Weeks: A Pragmatic Guide to Learning <br />

Programming Languages. Pragmatic Programmers, 2010. <br />

<strong>Actors</strong>: A Short Tutorial. http://www.scala-­‐lang.org/node/242 <br />

<strong>Scala</strong> Standard Library 2.8.1 Final. http://www.scala-­‐lang.org/api/current/ <br />

index.html <br />

Haller, Philipp and Martin Odersky. “<strong>Actors</strong> that Unify Threads and Events”. Lecture <br />

Notes in Computer Science. Vol 4467, pp 171-­‐190, 2007. <br />

<br />

7

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!