#region --------------- Copyright Dresser Wayne Pignone ------------- /* * $Log: /Wrk/WayneLibraries/Wrk/StateEngine/Generic/TimeoutState.cs $ * * 6 08-07-30 11:35 roger.månsson * * 5 08-05-07 15:35 roger.månsson * Obsoleted constructor with main object reference again. Instead, use * WritableMain property. When this is set on a composite state object, * the abstract method "ConfigureCompositeStateMachine" is called, and the * configuration of the state machine can be made. * * 4 08-04-24 15:45 Mattias.larsson * * 3 07-10-04 15:31 roger.månsson * Fixed glitch that let a timeout event slip out of the state even though * the state was left. It occured if the timeout was fired at the same * time the state exited for another reason. */ #endregion using System; using System.Collections.Generic; using System.Text; namespace Wayne.Lib.StateEngine.Generic { /// /// Generic timeout state class that has a main object of a generic type. /// /// Specifies the type of the main object. public abstract class TimeoutState : State { #region Fields Wayne.Lib.StateEngine.Timer timer; object myToken; #endregion #region Methods /// /// See State.Enter /// /// /// protected override void Enter(Wayne.Lib.StateEngine.StateEntry stateEntry, ref Wayne.Lib.StateEngine.Transition transition) { base.Enter(stateEntry, ref transition); myToken = new object(); var timeoutInterval = TimeoutInterval; if (timeoutInterval > 0) { timer = new Wayne.Lib.StateEngine.Timer(this, GenericEventType.Timeout, timeoutInterval, myToken); ActivateTimer(timer); } } /// /// HandleEvent is sealed, use HandleNonTimeoutEvent method to override instead. /// /// /// protected sealed override void HandleEvent(Wayne.Lib.StateEngine.StateEngineEvent stateEngineEvent, ref Wayne.Lib.StateEngine.Transition transition) { base.HandleEvent(stateEngineEvent, ref transition); if (stateEngineEvent.Type.Equals(GenericEventType.Timeout)) { Wayne.Lib.StateEngine.TimerEvent timerEvent = stateEngineEvent as Wayne.Lib.StateEngine.TimerEvent; if (timerEvent != null) { if (timerEvent.UserToken.Equals(myToken)) { Timeout(ref transition); timerEvent.Handled = true; timer = null; } } } if (!stateEngineEvent.Handled) HandleNonTimeoutEvent(stateEngineEvent, ref transition); } /// /// See State.Exit /// protected override void Exit() { base.Exit(); myToken = null; if (this.timer != null) { this.timer.Disable(); this.timer = null; } } /// /// Method that is implemented by descendant classes to receive events that were not the timeout event. /// /// /// protected abstract void HandleNonTimeoutEvent(Wayne.Lib.StateEngine.StateEngineEvent stateEngineEvent, ref Wayne.Lib.StateEngine.Transition transition); /// /// Method that is used by descendant classes to set the timeout of the state. /// /// protected abstract int TimeoutInterval { get;} /// /// Method that is used by descendant classes to be signaled when the timeout has fired. /// /// protected abstract void Timeout(ref Wayne.Lib.StateEngine.Transition transition); /// /// Cancels the currently running timer. /// protected void CancelTimer() { if (this.timer != null) { this.timer.Disable(); this.timer = null; } } /// /// Restarts the timer. If a timer is active, it is restarted, and if the timer is not active anymore, it is started again. /// protected void ResetTimer() { CancelTimer(); timer = new Wayne.Lib.StateEngine.Timer(this, GenericEventType.Timeout, TimeoutInterval, myToken); ActivateTimer(timer); } #endregion } }