add terminate(Shutdown) to FSM.postStop

This commit is contained in:
Roland 2011-05-31 22:27:18 +02:00
parent 89bc1943c3
commit ca36b556fb
3 changed files with 32 additions and 3 deletions

View file

@ -155,7 +155,6 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit {
case Ev("go") goto(2) case Ev("go") goto(2)
} }
}).start() }).start()
val reff = testActor
val logger = Actor.actorOf(new Actor { val logger = Actor.actorOf(new Actor {
def receive = { def receive = {
case x testActor forward x case x testActor forward x
@ -169,5 +168,18 @@ class FSMActorSpec extends WordSpec with MustMatchers with TestKit {
EventHandler.removeListener(logger) EventHandler.removeListener(logger)
} }
"run onTermination upon ActorRef.stop()" in {
lazy val fsm = new Actor with FSM[Int, Null] {
startWith(1, null)
when(1) { NullFunction }
onTermination {
case x testActor ! x
}
}
val ref = Actor.actorOf(fsm).start()
ref.stop()
expectMsg(fsm.StopEvent(Shutdown, 1, null))
}
} }
} }

View file

@ -480,6 +480,8 @@ trait FSM[S, D] extends ListenerManagement {
} }
} }
override def postStop { terminate(Shutdown) }
private def terminate(reason: Reason) = { private def terminate(reason: Reason) = {
reason match { reason match {
case Failure(ex: Throwable) EventHandler.error(ex, self, "terminating due to Failure") case Failure(ex: Throwable) EventHandler.error(ex, self, "terminating due to Failure")

View file

@ -430,8 +430,8 @@ queued it. The status of any timer may be inquired with
These named timers complement state timeouts because they are not affected by These named timers complement state timeouts because they are not affected by
intervening reception of other messages. intervening reception of other messages.
Termination Termination from Inside
----------- -----------------------
The FSM is stopped by specifying the result state as The FSM is stopped by specifying the result state as
@ -471,6 +471,21 @@ a :class:`StopEvent(reason, stateName, stateData)` as argument:
As for the :func:`whenUnhandled` case, this handler is not stacked, so each As for the :func:`whenUnhandled` case, this handler is not stacked, so each
invocation of :func:`onTermination` replaces the previously installed handler. invocation of :func:`onTermination` replaces the previously installed handler.
Termination from Outside
------------------------
When an :class:`ActorRef` associated to a FSM is stopped using the
:meth:`stop()` method, its :meth:`postStop` hook will be executed. The default
implementation by the :class:`FSM` trait is to execute the
:meth:`onTermination` handler if that is prepared to handle a
:obj:`StopEvent(Shutdown, ...)`.
.. warning::
In case you override :meth:`postStop` and want to have your
:meth:`onTermination` handler called, do not forget to call
``super.postStop``.
Examples Examples
======== ========