#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
}
}