add documentation and compat implicit to FSM

This commit is contained in:
Roland Kuhn 2011-04-07 10:52:14 +02:00
parent 3d04acf314
commit 42b72f0c4b
2 changed files with 57 additions and 2 deletions

View file

@ -98,6 +98,23 @@ object FSM {
* Each of the above also supports the method <code>replying(AnyRef)</code> for
* sending a reply before changing state.
*
* While changing state, custom handlers may be invoked which are registered
* using <code>onTransition</code>. This is meant to enable concentrating
* different concerns in different places; you may choose to use
* <code>when</code> for describing the properties of a state, including of
* course initiating transitions, but you can describe the transitions using
* <code>onTransision</code> to avoid having to duplicate that code among
* multiple paths which lead to a transition:
*
* <pre>
* onTransition {
* case Active -&gt; _ =&gt; cancelTimer("activeTimer")
* }
* </pre>
*
* 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 <code>SubscribeTransitionCallback</code> message to this actor;
* use <code>UnsubscribeTransitionCallback</code> before stopping the other
@ -247,12 +264,43 @@ trait FSM[S, D] {
/**
* Set handler which is called upon each state transition, i.e. not when
* staying in the same state.
* staying in the same state. This may use the pair extractor defined in the
* FSM companion object like so:
*
* <pre>
* onTransition {
* case Old -&gt; New =&gt; doSomething
* }
* </pre>
*
* It is also possible to supply a 2-ary function object:
*
* <pre>
* onTransition(handler _)
*
* private def handler(from: S, to: S) { ... }
* </pre>
*
* The underscore is unfortunately necessary to enable the nicer syntax shown
* above (it uses the implicit conversion total2pf under the hood).
*
* <b>Multiple handlers may be installed, and every one of them will be
* called, not only the first one matching.</b>
*/
protected final def onTransition(transitionHandler: TransitionHandler) = {
protected final def onTransition(transitionHandler: TransitionHandler) {
transitionEvent :+= transitionHandler
}
/**
* Convenience wrapper for using a total function instead of a partial
* function literal. To be used with onTransition.
*/
implicit protected final def total2pf(transitionHandler: (S, S) => Unit) =
new PartialFunction[(S, S), Unit] {
def isDefinedAt(in : (S, S)) = true
def apply(in : (S, S)) { transitionHandler(in._1, in._2) }
}
/**
* Set handler which is called upon termination of this FSM actor.
*/

View file

@ -68,6 +68,13 @@ object FSMActorSpec {
case Locked -> Open => transitionLatch.open
}
// verify that old-style does still compile
onTransition (transitionHandler _)
def transitionHandler(from: LockState, to: LockState) = {
// dummy
}
onTermination {
case StopEvent(Shutdown, Locked, _) =>
// stop is called from lockstate with shutdown as reason...