From 33a628a0d11681da80625d37dc44b8d4f08f252c Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 3 Jan 2011 11:12:40 +0100 Subject: [PATCH 1/5] stop the timers (if any) while terminating --- akka-actor/src/main/scala/akka/actor/FSM.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index 10a0944147..81078f59be 100755 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -378,6 +378,7 @@ trait FSM[S, D] { } private def terminate(reason: Reason) = { + timers.foreach{ case (timer, t) => log.slf4j.info("Canceling timer {}", timer); t.cancel} terminateEvent.apply(StopEvent(reason, currentState.stateName, currentState.stateData)) self.stop } From 9f664711c03a69d21737a9fad96dee38253457fb Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 3 Jan 2011 11:35:27 +0100 Subject: [PATCH 2/5] - make transition handler a function taking old and new state avoiding the default use of the transition class - only create transition class when transition listeners are subscribed --- akka-actor/src/main/scala/akka/actor/FSM.scala | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index 81078f59be..00bdf75d6e 100755 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -6,7 +6,7 @@ package akka.actor import akka.util._ import scala.collection.mutable -import java.util.concurrent.{ScheduledFuture, TimeUnit} +import java.util.concurrent.ScheduledFuture object FSM { @@ -124,6 +124,7 @@ trait FSM[S, D] { type StateFunction = scala.PartialFunction[Event[D], State] type Timeout = Option[Duration] + type TransitionHandler = (S, S) => Unit /* DSL */ @@ -245,7 +246,7 @@ trait FSM[S, D] { * Set handler which is called upon each state transition, i.e. not when * staying in the same state. */ - protected final def onTransition(transitionHandler: PartialFunction[Transition[S], Unit]) = { + protected final def onTransition(transitionHandler: TransitionHandler) = { transitionEvent = transitionHandler } @@ -306,8 +307,8 @@ trait FSM[S, D] { case StopEvent(reason, _, _) => log.slf4j.info("Stopping because of reason: {}", reason) } - private var transitionEvent: PartialFunction[Transition[S], Unit] = { - case Transition(from, to) => log.slf4j.debug("Transitioning from state {} to {}", from, to) + private var transitionEvent: TransitionHandler = (from, to) => { + log.slf4j.debug("Transitioning from state {} to {}", from, to) } override final protected def receive: Receive = { @@ -358,9 +359,11 @@ trait FSM[S, D] { terminate(Failure("Next state %s does not exist".format(nextState.stateName))) } else { if (currentState.stateName != nextState.stateName) { - val transition = Transition(currentState.stateName, nextState.stateName) - transitionEvent.apply(transition) - transitionCallBackList.foreach(_ ! transition) + transitionEvent.apply(currentState.stateName, nextState.stateName) + if (!transitionCallBackList.isEmpty) { + val transition = Transition(currentState.stateName, nextState.stateName) + transitionCallBackList.foreach(_ ! transition) + } } applyState(nextState) } From 80ac75ac38a041bc0bdc07b5423d2ad9011544a7 Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 3 Jan 2011 11:40:04 +0100 Subject: [PATCH 3/5] fix tests --- akka-actor/src/test/scala/akka/actor/actor/FSMActorSpec.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/akka-actor/src/test/scala/akka/actor/actor/FSMActorSpec.scala b/akka-actor/src/test/scala/akka/actor/actor/FSMActorSpec.scala index 397517e05e..f9dc185597 100644 --- a/akka-actor/src/test/scala/akka/actor/actor/FSMActorSpec.scala +++ b/akka-actor/src/test/scala/akka/actor/actor/FSMActorSpec.scala @@ -67,10 +67,10 @@ object FSMActorSpec { } } - onTransition { + onTransition((oldState, newState) => Transition(oldState, newState) match { case Transition(Locked, Open) => transitionLatch.open case Transition(_, _) => () - } + }) onTermination { case StopEvent(Shutdown, Locked, _) => From 61b4ded1bda00cbd23666898b3f6c1ddd7661736 Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 3 Jan 2011 12:03:38 +0100 Subject: [PATCH 4/5] Removed generic typed classes that are only used in the FSM itself from the companion object and put back in the typed FSM again so they will take same types. --- akka-actor/src/main/scala/akka/actor/FSM.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index 00bdf75d6e..f25d4ea164 100755 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -10,11 +10,6 @@ import java.util.concurrent.ScheduledFuture object FSM { - case class Event[D](event: Any, stateData: D) - object Ev { - def unapply[D](e : Event[D]) : Option[Any] = Some(e.event) - } - case class Transition[S](from: S, to: S) case class SubscribeTransitionCallBack(actorRef: ActorRef) case class UnsubscribeTransitionCallBack(actorRef: ActorRef) @@ -23,7 +18,6 @@ object FSM { case object Normal extends Reason case object Shutdown extends Reason case class Failure(cause: Any) extends Reason - case class StopEvent[S, D](reason: Reason, currentState: S, stateData: D) case object StateTimeout case class TimeoutMarker(generation: Long) @@ -386,6 +380,10 @@ trait FSM[S, D] { self.stop } + case class Event[D](event: Any, stateData: D) + object Ev { + def unapply[D](e : Event[D]) : Option[Any] = Some(e.event) + } case class State(stateName: S, stateData: D, timeout: Timeout = None) { @@ -427,4 +425,5 @@ trait FSM[S, D] { } } + case class StopEvent[S, D](reason: Reason, currentState: S, stateData: D) } From 5094e87df78226fe7555c976c628951520ae8308 Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 3 Jan 2011 19:37:23 +0100 Subject: [PATCH 5/5] Move handleEvent var declaration _after_ handleEventDefault val declaration. Using a val before defining it causes nullpointer exceptions... --- akka-actor/src/main/scala/akka/actor/FSM.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-actor/src/main/scala/akka/actor/FSM.scala b/akka-actor/src/main/scala/akka/actor/FSM.scala index f25d4ea164..3140fd9cdf 100755 --- a/akka-actor/src/main/scala/akka/actor/FSM.scala +++ b/akka-actor/src/main/scala/akka/actor/FSM.scala @@ -288,12 +288,12 @@ trait FSM[S, D] { } } - private var handleEvent: StateFunction = handleEventDefault private val handleEventDefault: StateFunction = { case Event(value, stateData) => log.slf4j.warn("Event {} not handled in state {}, staying at current state", value, currentState.stateName) stay } + private var handleEvent: StateFunction = handleEventDefault private var terminateEvent: PartialFunction[StopEvent[S,D], Unit] = { case StopEvent(Failure(cause), _, _) =>