This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Actors "link" Help

1 reply
Bastian, Mark
Joined: 2009-01-16,
User offline. Last seen 42 years 45 weeks ago.
Actors "link" Help Here’s a very simple program I am working on to try to understand actor linking. If I understand correctly, once I link the actors, a message sent to one will be forwarded to the other, but there’s no documentation on this, so I am totally guessing. I’ve created the attached spike solution in an attempt to create some sort of interesting behavior, but nothing noticeable seems to happen.

I would expect that once I do the link, messages I send to actor1 would also be sent to listener. Is that correct? If not, what is the right behavior? I am using 2.7.7 final.

Thanks,
Mark

package spikes

import scala.actors._
import scala.actors.Actor._

object ActorLinking {
  def main(args : Array[String]) : Unit = {
    println("Exploring actor linking")
    
    actor1 ! "Pre link"
   listener ! "Pre link"
   actor1 ! Listen(listener)
    actor1 ! "Post link"
   listener ! "Post link"
   
    actor1 ! 'exit
   
    println("I don't get it")
  }
  
  case class Listen(actor : Actor)
  
  val actor1 : Actor = actor {
    loop {
      react {
        case Listen(x) => link(x)
        case 'exit => exit
       case x => println("actor1: " + x)
      }
    }
  }
  
  val listener = actor {
    loop {
      react {
        case 'exit => exit
        case x => println("listener: " + x)
      }
    }
  }
}
Colin Bullock
Joined: 2009-01-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Actors "link" Help
Linking actors isn't about messages or forwarding, it's about failure.

Consider the following example:

val divide = actor {
  // The other half of error handling
  self.trapExit = true

  def newLinkedWorker = {
    val worker = actor { loop { react {
      case (x: Int, y: Int) => println(x + " / " + y + " = "  + (x / y))
    }}}
    self link worker
    worker
  }

  // Message handler loop
  def run(worker: Actor): Nothing = react {
    case (x: Int, y: Int) =>
      worker ! (x, y)
      run(worker)
    case Exit(deadWorker, reason) =>
      println("Worker died because of: " + reason)
      run(newLinkedWorker)
  }

  run(newLinkedWorker)
}

In this contrived example, the actor divide takes a tuple of integers and prints the result of dividing them. It does so by creating another actor to do the actual work. These two actors are linked, and the main actor traps exits. Linking means that when either one of them dies, one of two things will happen: if the linked actor traps exits, it will receive a message indicating who died and why; if the linked actor does not trap exits, it will die too (which will be propagated to other actors linked to it, etc, etc).

In the example above, if you send call divide ! (1, 0) the worker actor dies due to divide-by-zero. The main actor is notified, replaces it's worker with a new linked actor, and happily continues to serve other clients who are looking to divide more sensible numbers.

If you're looking for more information on the subject, some very good information can be found in Joe Armstrong's erlang book from Pragmatic Programmers. The chapters on error handling do a good job of introducing these and related concepts (obviously, in erlang, but the concepts map almost directly to scala).

- Colin

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland