Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala, check if Actor has exited

in Scala 2.8 when I start actors, I can communicate via message passing. This in turn means that I can send the ultimate Exit() message or whatever I decide fits my protocol.

But how will I check if an actor has exited? I can easily imagine myself having a task where a master actor starts some worker actors and then simply waits for the answers, each time checking if this was the final answer (i.e. are any Actors still working or did they all exit?).

Of course I can let them all send back an "I'm done" message, and then count them, but this is somehow unsatisfactory.

What is best practise when testing for the completion of worker-actors?

EDIT#1

I am looking into Futures, but having trouble. Can someone explain why this code doesn't work:

package test
import scala.actors.Futures._

object FibFut extends Application{
    
    def fib(i:Int):Int = 
        if(i<2)
            1
        else
            fib(i-1)+fib(i-2)
            
    val f = future{ fib(3) }
    
    println(f())    
        
}

It works if I define the function fib inside the future-body. It must be a scope thing, but I don't get any errors with the above, it simply hangs. Anyone?

EDIT#2

It seems that extending Application wasn't a nice way to go. Defining a main method made everything work. The below code is what I was looking for, so Futures get the thumbs up :)

package test

import scala.actors.Futures._

object FibFut {

  def fib(i: Int): Int = if (i < 2) 1 else fib(i - 1) + fib(i - 2)

  def main(args: Array[String]) {

    val fibs = for (i <- 0 to 50) yield future { fib(i) }

    for (future <- fibs) println(future())

  }

}
like image 850
Felix Avatar asked Nov 28 '10 15:11

Felix


2 Answers

I'm a fan of "I'm done" messages, personally; it's a good way to manage distribution of work, and as a bonus, you already know when all children have finished what they're doing.

But if you really just want to farm out some work once and wait until everything is ready, check out scala.actors.Futures. You can ask it to do some computation:

val futureA = Futures.future {
  val a = veryExpensiveOperation
  (a,"I'm from the future!")
}

and then you can wait for everything to complete, if you have made multiple requests:

Futures.awaitAll(600*1000, futureA, futureB, futureC, futureD)
// Returns once all of A-D have been computed
val actualA = futureA()   // Now we get the value
like image 104
Rex Kerr Avatar answered Oct 17 '22 10:10

Rex Kerr


A while ago I wrote a post on linking actors in Scala. Actor linking is an idiomatic [and the easiest] way to monitor actors in Erlang, Scala Actors and other actor libraries. By defalt, when you link 2 actors, and one of them dies, another immediately dies too (unless the actor traps/handles exit signal):

scala> case object Stop
defined module Stop

scala>

scala> val actor1 = actor {
     |    loop {
     |       react {
     |          case Stop =>
     |             println("Actor 1: stop")
     |             exit()
     |          case msg => println(msg)
     |             }
     |         }
     | }
actor1: scala.actors.Actor = scala.actors.Actor$$anon$1@1feea62

scala>

scala> val actor2 = actor {
     |    link(actor1)
     |    self.trapExit = true
     |    loop {
     |       react {
     |          case msg => println(msg)
     |             }
     |         }
     | }
actor2: scala.actors.Actor = scala.actors.Actor$$anon$1@1e1c66a

scala> actor1.start
res12: scala.actors.Actor = scala.actors.Actor$$anon$1@1feea62

scala> actor2.start
res13: scala.actors.Actor = scala.actors.Actor$$anon$1@1e1c66a

scala> actor1 ! Stop
Actor 1: stop

scala> Exit(scala.actors.Actor$$anon$1@1feea62,'normal)  // Actor 2 received message, when Actor1 died

A more sophisticated and flexible way is using supervisors (supervisor behavior in Erlang, actor supervisors in Akka Actors library, etc). A supervisor (being itself an actor) monitors a number of other actors, and restarts them with regards to a specified strategy (restart all actors, if one dies; restart just one actor, when it dies).

like image 2
Vasil Remeniuk Avatar answered Oct 17 '22 10:10

Vasil Remeniuk