Skip to content

Commit

Permalink
fix cancellation of FSM state timeout by named timer messages, fixes #…
Browse files Browse the repository at this point in the history
…1108

- actually cancel state timeout timer
- increment generation timer in case it had already fired
  • Loading branch information
rkuhn committed Aug 14, 2011
1 parent 7e1a3fe commit 027d1ee
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ class FSMTimingSpec extends WordSpec with MustMatchers with TestKit {
expectMsg(Transition(fsm, TestCancelTimer, Initial))
}

"not get confused between named and state timers" in {
fsm ! TestCancelStateTimerInNamedTimerMessage
fsm ! Tick
expectMsg(100 millis, Tick)
Thread.sleep(200)
fsm.dispatcher resume fsm
expectMsg(100 millis, Transition(fsm, TestCancelStateTimerInNamedTimerMessage, TestCancelStateTimerInNamedTimerMessage2))
fsm ! Cancel
within(100 millis) {
expectMsg(Cancel)
expectMsg(Transition(fsm, TestCancelStateTimerInNamedTimerMessage2, Initial))
}
}

"receive and cancel a repeated timer" in {
fsm ! TestRepeatedTimer
val seq = receiveWhile(600 millis) {
Expand Down Expand Up @@ -113,6 +127,8 @@ object FSMTimingSpec {
case object TestRepeatedTimer extends State
case object TestUnhandled extends State
case object TestCancelTimer extends State
case object TestCancelStateTimerInNamedTimerMessage extends State
case object TestCancelStateTimerInNamedTimerMessage2 extends State

case object Tick
case object Tock
Expand Down Expand Up @@ -170,6 +186,21 @@ object FSMTimingSpec {
stay using (remaining - 1)
}
}
when(TestCancelStateTimerInNamedTimerMessage) {
// FSM is suspended after processing this message and resumed 200ms later
case Ev(Tick)
self.dispatcher suspend self
setTimer("named", Tock, 10 millis, false)
stay forMax (100 millis) replying Tick
case Ev(Tock)
goto(TestCancelStateTimerInNamedTimerMessage2)
}
when(TestCancelStateTimerInNamedTimerMessage2) {
case Ev(StateTimeout)
goto(Initial)
case Ev(Cancel)
goto(Initial) replying Cancel
}
when(TestUnhandled) {
case Ev(SetHandler)
whenUnhandled {
Expand Down
9 changes: 7 additions & 2 deletions akka-actor/src/main/scala/akka/actor/FSM.scala
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,13 @@ trait FSM[S, D] extends ListenerManagement {
if (generation == gen) {
processMsg(StateTimeout, "state timeout")
}
case t@Timer(name, msg, repeat, generation)
if ((timers contains name) && (timers(name).generation == generation)) {
case t @ Timer(name, msg, repeat, gen)
if ((timers contains name) && (timers(name).generation == gen)) {
if (timeoutFuture.isDefined) {
timeoutFuture.get.cancel(true)
timeoutFuture = None
}
generation += 1
processMsg(msg, t)
if (!repeat) {
timers -= name
Expand Down

0 comments on commit 027d1ee

Please sign in to comment.