|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
public interface FSM<S,D>
Finite State Machine actor trait. Use as follows:
object A { trait State case class One extends State case class Two extends State case class Data(i : Int) } class A extends Actor with FSM[A.State, A.Data] { import A._ startWith(One, Data(42)) when(One) { case Event(SomeMsg, Data(x)) => ... case Ev(SomeMsg) => ... // convenience when data not needed } when(Two, stateTimeout = 5 seconds) { ... } initialize() }
Within the partial function the following values are returned for effecting state transitions:
- stay
for staying in the same state
- stay using Data(...)
for staying in the same state, but with
different data
- stay forMax 5.millis
for staying with a state timeout; can be
combined with using
- goto(...)
for changing into a different state; also supports
using
and forMax
- stop
for terminating this FSM actor
Each of the above also supports the method replying(AnyRef)
for
sending a reply before changing state.
While changing state, custom handlers may be invoked which are registered
using onTransition
. This is meant to enable concentrating
different concerns in different places; you may choose to use
when
for describing the properties of a state, including of
course initiating transitions, but you can describe the transitions using
onTransition
to avoid having to duplicate that code among
multiple paths which lead to a transition:
onTransition { case Active -> _ => cancelTimer("activeTimer") }
Multiple such blocks are supported and all of them will be called, not only the first matching one.
Another feature is that other actors may subscribe for transition events by
sending a SubscribeTransitionCallback
message to this actor;
use UnsubscribeTransitionCallback
before stopping the other
actor.
State timeouts set an upper bound to the time which may pass before another message is received in the current state. If no external message is available, then upon expiry of the timeout a StateTimeout message is sent. Note that this message will only be received in the state for which the timeout was set and that any message received will cancel the timeout (possibly to be started again by the next transition).
Another feature is the ability to install and cancel single-shot as well as repeated timers which arrange for the sending of a user-specified message:
setTimer("tock", TockMsg, 1 second, true) // repeating setTimer("lifetime", TerminateMsg, 1 hour, false) // single-shot cancelTimer("tock") isTimerActive("tock")
Nested Class Summary | |
---|---|
static class |
FSM.$minus$greater$
This extractor is just convenience for matching a (S, S) pair, including a reminder what the new state is. |
static class |
FSM.CurrentState<S>
Message type which is sent directly to the subscribed actor in FSM.SubscribeTransitionCallBack before sending any
FSM.Transition messages. |
static class |
FSM.CurrentState$
|
static class |
FSM.Event
All messages sent to the FSM will be wrapped inside an
Event , which allows pattern matching to extract both state and data. |
static class |
FSM.Event$
|
static class |
FSM.Failure
Signifies that the FSM is shutting itself down because of
an error, e.g. |
static class |
FSM.Failure$
|
static class |
FSM.LogEntry<S,D>
Log Entry of the LoggingFSM , can be obtained by calling getLog . |
static class |
FSM.LogEntry$
|
static class |
FSM.Normal$
Default reason if calling stop() . |
static class |
FSM.NullFunction$
A partial function value which does not match anything and can be used to “reset” whenUnhandled and onTermination handlers. |
static interface |
FSM.Reason
Reason why this FSM is shutting down. |
static class |
FSM.Shutdown$
Reason given when someone was calling system.stop(fsm) from outside;
also applies to Stop supervision directive. |
static class |
FSM.State<S,D>
This captures all of the managed state of the FSM : the state
name, the state data, possibly custom timeout, stop reason and replies
accumulated while processing the last message. |
static class |
FSM.State$
|
static class |
FSM.StateTimeout$
This case object is received in case of a state timeout. |
static class |
FSM.StopEvent
Case class representing the state of the FSM whithin the
onTermination block. |
static class |
FSM.StopEvent$
|
static class |
FSM.SubscribeTransitionCallBack
Send this to an FSM to request first the FSM.CurrentState
and then a series of FSM.Transition updates. |
static class |
FSM.SubscribeTransitionCallBack$
|
private static class |
FSM.TimeoutMarker
INTERNAL API |
private static class |
FSM.TimeoutMarker$
|
private static class |
FSM.Timer
INTERNAL API |
private static class |
FSM.Timer$
|
static class |
FSM.TransformHelper
|
static class |
FSM.Transition<S>
Message type which is used to communicate transitions between states to all subscribed listeners (use FSM.SubscribeTransitionCallBack ). |
static class |
FSM.Transition$
|
static class |
FSM.UnsubscribeTransitionCallBack
Unsubscribe from FSM.Transition notifications which was
effected by sending the corresponding FSM.SubscribeTransitionCallBack . |
static class |
FSM.UnsubscribeTransitionCallBack$
|
Nested classes/interfaces inherited from interface akka.actor.Actor |
---|
Actor.emptyBehavior$ |
Method Summary | |
---|---|
void |
applyState(FSM.State<S,D> nextState)
|
void |
cancelTimer(java.lang.String name)
Cancel named timer, ensuring that the message is not subsequently delivered (no race). |
FSM.State<S,D> |
currentState()
|
boolean |
debugEvent()
|
long |
generation()
|
scala.PartialFunction<FSM.Event,FSM.State<S,D>> |
handleEvent()
|
scala.PartialFunction<FSM.Event,FSM.State<S,D>> |
handleEventDefault()
|
void |
handleTransition(S prev,
S next)
|
void |
initialize()
Verify existence of initial state and setup timers. |
boolean |
isStateTimerActive()
INTERNAL API, used for testing. |
boolean |
isTimerActive(java.lang.String name)
Inquire whether the named timer is still active. |
void |
logTermination(FSM.Reason reason)
By default FSM.Failure is logged at error level and other reason
types are not logged. |
void |
makeTransition(FSM.State<S,D> nextState)
|
FSM.State<S,D> |
nextState()
|
D |
nextStateData()
Return next state data (available in onTransition handlers) |
void |
onTermination(scala.PartialFunction<FSM.StopEvent,scala.runtime.BoxedUnit> terminationHandler)
Set handler which is called upon termination of this FSM actor. |
void |
onTransition(scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> transitionHandler)
Set handler which is called upon each state transition, i.e. |
void |
postStop()
Call onTermination hook; if you want to retain this behavior when
overriding make sure to call super.postStop() . |
void |
processEvent(FSM.Event event,
java.lang.Object source)
|
void |
processMsg(java.lang.Object value,
java.lang.Object source)
|
scala.PartialFunction<java.lang.Object,scala.runtime.BoxedUnit> |
receive()
This defines the initial actor behavior, it must return a partial function with the actor logic. |
void |
register(S name,
scala.PartialFunction<FSM.Event,FSM.State<S,D>> function,
scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
|
void |
setStateTimeout(S state,
scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
Set state timeout explicitly. |
void |
setTimer(java.lang.String name,
java.lang.Object msg,
scala.concurrent.duration.FiniteDuration timeout,
boolean repeat)
Schedule named timer to deliver message after given delay, possibly repeating. |
void |
startWith(S stateName,
D stateData,
scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
Set initial state. |
D |
stateData()
Return current state data (i.e. |
scala.collection.mutable.Map<S,scala.PartialFunction<FSM.Event,FSM.State<S,D>>> |
stateFunctions()
|
S |
stateName()
Return current state name (i.e. |
FSM.StateTimeout$ |
StateTimeout()
This case object is received in case of a state timeout. |
scala.collection.mutable.Map<S,scala.Option<scala.concurrent.duration.FiniteDuration>> |
stateTimeouts()
|
FSM.State<S,D> |
stay()
Produce "empty" transition descriptor. |
FSM.State<S,D> |
stop()
Produce change descriptor to stop this FSM actor with reason "Normal". |
FSM.State<S,D> |
stop(FSM.Reason reason)
Produce change descriptor to stop this FSM actor including specified reason. |
FSM.State<S,D> |
stop(FSM.Reason reason,
D stateData)
Produce change descriptor to stop this FSM actor including specified reason. |
void |
terminate(FSM.State<S,D> nextState)
|
scala.PartialFunction<FSM.StopEvent,scala.runtime.BoxedUnit> |
terminateEvent()
|
scala.Option<Cancellable> |
timeoutFuture()
|
scala.collection.Iterator<java.lang.Object> |
timerGen()
|
scala.collection.mutable.Map<java.lang.String,FSM.Timer> |
timers()
|
scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> |
total2pf(scala.Function2<S,S,scala.runtime.BoxedUnit> transitionHandler)
Convenience wrapper for using a total function instead of a partial function literal. |
FSM.TransformHelper |
transform(scala.PartialFunction<FSM.Event,FSM.State<S,D>> func)
|
scala.collection.immutable.List<scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit>> |
transitionEvent()
|
void |
when(S stateName,
scala.concurrent.duration.FiniteDuration stateTimeout,
scala.PartialFunction<FSM.Event,FSM.State<S,D>> stateFunction)
Insert a new StateFunction at the end of the processing chain for the given state. |
void |
whenUnhandled(scala.PartialFunction<FSM.Event,FSM.State<S,D>> stateFunction)
Set handler which is called upon reception of unhandled messages. |
Methods inherited from interface akka.actor.Actor |
---|
context, noSender, postRestart, preRestart, preStart, self, sender, supervisorStrategy, unhandled |
Methods inherited from interface akka.routing.Listeners |
---|
gossip, listenerManagement, listeners |
Methods inherited from interface akka.actor.ActorLogging |
---|
log |
Method Detail |
---|
FSM.StateTimeout$ StateTimeout()
void when(S stateName, scala.concurrent.duration.FiniteDuration stateTimeout, scala.PartialFunction<FSM.Event,FSM.State<S,D>> stateFunction)
stateName
- designator for the statestateTimeout
- default state timeout for this statestateFunction
- partial function describing response to inputvoid startWith(S stateName, D stateData, scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
initialize()
method.
If different state is needed after a restart this method, followed by initialize()
, can
be used in the actor life cycle hooks Actor.preStart()
and Actor.postRestart(java.lang.Throwable)
.
stateName
- initial state designatorstateData
- initial state datatimeout
- state timeout for the initial state, overriding the default timeout for that stateFSM.State<S,D> stay()
FSM.State<S,D> stop()
FSM.State<S,D> stop(FSM.Reason reason)
FSM.State<S,D> stop(FSM.Reason reason, D stateData)
FSM.TransformHelper transform(scala.PartialFunction<FSM.Event,FSM.State<S,D>> func)
void setTimer(java.lang.String name, java.lang.Object msg, scala.concurrent.duration.FiniteDuration timeout, boolean repeat)
name
- identifier to be used with cancelTimer()msg
- message to be deliveredtimeout
- delay of first message delivery and between subsequent messagesrepeat
- send once if false, scheduleAtFixedRate if truevoid cancelTimer(java.lang.String name)
name
- of the timer to cancelboolean isTimerActive(java.lang.String name)
void setStateTimeout(S state, scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
boolean isStateTimerActive()
void onTransition(scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> transitionHandler)
onTransition { case Old -> New => doSomething }
It is also possible to supply a 2-ary function object:
onTransition(handler _) private def handler(from: S, to: S) { ... }
The underscore is unfortunately necessary to enable the nicer syntax shown above (it uses the implicit conversion total2pf under the hood).
Multiple handlers may be installed, and every one of them will be called, not only the first one matching.
scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit> total2pf(scala.Function2<S,S,scala.runtime.BoxedUnit> transitionHandler)
void onTermination(scala.PartialFunction<FSM.StopEvent,scala.runtime.BoxedUnit> terminationHandler)
void whenUnhandled(scala.PartialFunction<FSM.Event,FSM.State<S,D>> stateFunction)
The current state may be queried using stateName
.
void initialize()
Actor.preStart()
and
Actor.postRestart(java.lang.Throwable)
startWith(S, D, scala.Option)
S stateName()
D stateData()
D nextStateData()
boolean debugEvent()
FSM.State<S,D> currentState()
scala.Option<Cancellable> timeoutFuture()
FSM.State<S,D> nextState()
long generation()
scala.collection.mutable.Map<java.lang.String,FSM.Timer> timers()
scala.collection.Iterator<java.lang.Object> timerGen()
scala.collection.mutable.Map<S,scala.PartialFunction<FSM.Event,FSM.State<S,D>>> stateFunctions()
scala.collection.mutable.Map<S,scala.Option<scala.concurrent.duration.FiniteDuration>> stateTimeouts()
void register(S name, scala.PartialFunction<FSM.Event,FSM.State<S,D>> function, scala.Option<scala.concurrent.duration.FiniteDuration> timeout)
scala.PartialFunction<FSM.Event,FSM.State<S,D>> handleEventDefault()
scala.PartialFunction<FSM.Event,FSM.State<S,D>> handleEvent()
scala.PartialFunction<FSM.StopEvent,scala.runtime.BoxedUnit> terminateEvent()
scala.collection.immutable.List<scala.PartialFunction<scala.Tuple2<S,S>,scala.runtime.BoxedUnit>> transitionEvent()
void handleTransition(S prev, S next)
scala.PartialFunction<java.lang.Object,scala.runtime.BoxedUnit> receive()
Actor
receive
in interface Actor
void processMsg(java.lang.Object value, java.lang.Object source)
void processEvent(FSM.Event event, java.lang.Object source)
void applyState(FSM.State<S,D> nextState)
void makeTransition(FSM.State<S,D> nextState)
void postStop()
onTermination
hook; if you want to retain this behavior when
overriding make sure to call super.postStop()
.
Please note that this method is called by default from preRestart()
,
so override that one if onTermination
shall not be called during
restart.
postStop
in interface Actor
void terminate(FSM.State<S,D> nextState)
void logTermination(FSM.Reason reason)
FSM.Failure
is logged at error level and other reason
types are not logged. It is possible to override this behavior.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |