fix bug in ActorRef.stop() implementation

- it was telling all children to stop(), then waited for the
  ChildTerminated messages and finally terminated itself
- this worked fine, except when the stop came from the supervisor, i.e.
  the recipient was suspended and did not process the ChildTerminated
- so, as the mirror of Supervise() that it is, I changed
  ChildTerminated() to be a system message and instead of stopping
  processing normal messages by checking the stopping flag, just suspend
  the actor while awaiting the ChildTerminated's to flow in.
This commit is contained in:
Roland 2011-12-03 18:16:41 +01:00
parent 3d0bb8b415
commit 4c1d722398
7 changed files with 29 additions and 26 deletions

View file

@ -28,6 +28,9 @@ object Mailbox {
// secondary status: Scheduled bit may be added to Open/Suspended
final val Scheduled = 4
// mailbox debugging helper using println (see below)
// FIXME TODO take this out before release (but please leave in until M2!)
final val debug = false
}
/**
@ -164,6 +167,7 @@ abstract class Mailbox(val actor: ActorCell) extends MessageQueue with SystemMes
var processedMessages = 0
val deadlineNs = if (dispatcher.isThroughputDeadlineTimeDefined) System.nanoTime + dispatcher.throughputDeadlineTime.toNanos else 0
do {
if (debug) println(actor.self + " processing message " + nextMessage)
actor invoke nextMessage
processAllSystemMessages() //After we're done, process all system messages
@ -186,6 +190,7 @@ abstract class Mailbox(val actor: ActorCell) extends MessageQueue with SystemMes
var nextMessage = systemDrain()
try {
while (nextMessage ne null) {
if (debug) println(actor.self + " processing system message " + nextMessage + " with children " + actor.childrenRefs)
actor systemInvoke nextMessage
nextMessage = nextMessage.next
// dont ever execute normal message when system message present!
@ -240,6 +245,7 @@ trait DefaultSystemMessageQueue { self: Mailbox ⇒
@tailrec
final def systemEnqueue(receiver: ActorRef, message: SystemMessage): Unit = {
assert(message.next eq null)
if (Mailbox.debug) println(actor.self + " having enqueued " + message)
val head = systemQueueGet
/*
* this write is safely published by the compareAndSet contained within