Exceptions and react

Code surrounding an invocation of react should never catch instances of java.lang.Throwable. Doing so would interfere with internal exceptions used for flow control. By contrast, catching instances of (subtypes of) java.lang.Exception is always safe.

The fact that the current thread's call stack is discarded when an event-based actor suspends bears an important consequence on the event-based actor programming model: a call to react never returns normally. Instead, react always throws an internal control exception, which the actor runtime handles. Like any Scala or Java method, react could return normally only if its full call stack was available when it executed. Since that isn't the case with event-based actors, a call to react never returns.

The fact that react never returns means that no code can follow a react method invocation: Since react doesn't return, code following react would never execute. Thus, invoking react must always be the last thing an event-based actor does before it terminates. For example, in Listing 5.3 the actor won't print "finished" since it follows the call to react. This problem is corrected by moving the expression that prints "finished" into the body of the react call, as shown in Listing 5.4.

    actor {
      react {
        case "hello" =>
          println("hi")
      }
      println("finished")
    }
Listing 5.3 - Incorrect use of react.

    actor {
      react {
        case "hello" =>
          println("hi")
          println("finished")
      }
    }
Listing 5.4 - Correct use of react.

Since an actor's main job is to handle interesting messages, and since react defines an event-based message-handling mechanism for actors, you might think that react will always be the last, and even only, thing an actor needs to do. However, it is sometimes convenient to perform several react invocations in succession. In those situations, you could nest react invocations in sequence, as we saw in Listing 5.1.

Alternatively, you could define a recursive method that calls react several times in sequence. For instance, we can extend our simple chain example so that an actor waits for a specified number of 'Die messages before it terminates. Listing 5.5 shows how to do this by replacing the body of the chain actors with a call to the waitFor method. The waitFor method tests up front whether the current actor should terminate (if n == 0) or continue waiting for messages. The protocol logic is the same as before. The only difference is that after each message sends to from, we added a recursive call to waitFor.

    def waitFor(n: Int): Unit = if (n > 0) {
      react {
        case 'Die =>
          val from = sender
          if (next != null) {
            next ! 'Die
            react {
              case 'Ack => from ! 'Ack; waitFor(n - 1)
            }
          } else { from ! 'Ack; waitFor(n - 1) }
      }
    }
Listing 5.5 - Sequencing react calls using a recursive method.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset