TimeoutState.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #region --------------- Copyright Dresser Wayne Pignone -------------
  2. /*
  3. * $Log: /Wrk/WayneLibraries/Wrk/StateEngine/Generic/TimeoutState.cs $
  4. *
  5. * 6 08-07-30 11:35 roger.månsson
  6. *
  7. * 5 08-05-07 15:35 roger.månsson
  8. * Obsoleted constructor with main object reference again. Instead, use
  9. * WritableMain property. When this is set on a composite state object,
  10. * the abstract method "ConfigureCompositeStateMachine" is called, and the
  11. * configuration of the state machine can be made.
  12. *
  13. * 4 08-04-24 15:45 Mattias.larsson
  14. *
  15. * 3 07-10-04 15:31 roger.månsson
  16. * Fixed glitch that let a timeout event slip out of the state even though
  17. * the state was left. It occured if the timeout was fired at the same
  18. * time the state exited for another reason.
  19. */
  20. #endregion
  21. using System;
  22. using System.Collections.Generic;
  23. using System.Text;
  24. namespace Wayne.Lib.StateEngine.Generic
  25. {
  26. /// <summary>
  27. /// Generic timeout state class that has a main object of a generic type.
  28. /// </summary>
  29. /// <typeparam name="TMain">Specifies the type of the main object.</typeparam>
  30. public abstract class TimeoutState<TMain> : State<TMain>
  31. {
  32. #region Fields
  33. Wayne.Lib.StateEngine.Timer timer;
  34. object myToken;
  35. #endregion
  36. #region Methods
  37. /// <summary>
  38. /// See State.Enter
  39. /// </summary>
  40. /// <param name="stateEntry"></param>
  41. /// <param name="transition"></param>
  42. protected override void Enter(Wayne.Lib.StateEngine.StateEntry stateEntry, ref Wayne.Lib.StateEngine.Transition transition)
  43. {
  44. base.Enter(stateEntry, ref transition);
  45. myToken = new object();
  46. var timeoutInterval = TimeoutInterval;
  47. if (timeoutInterval > 0)
  48. {
  49. timer = new Wayne.Lib.StateEngine.Timer(this, GenericEventType.Timeout, timeoutInterval, myToken);
  50. ActivateTimer(timer);
  51. }
  52. }
  53. /// <summary>
  54. /// HandleEvent is sealed, use HandleNonTimeoutEvent method to override instead.
  55. /// </summary>
  56. /// <param name="stateEngineEvent"></param>
  57. /// <param name="transition"></param>
  58. protected sealed override void HandleEvent(Wayne.Lib.StateEngine.StateEngineEvent stateEngineEvent, ref Wayne.Lib.StateEngine.Transition transition)
  59. {
  60. base.HandleEvent(stateEngineEvent, ref transition);
  61. if (stateEngineEvent.Type.Equals(GenericEventType.Timeout))
  62. {
  63. Wayne.Lib.StateEngine.TimerEvent timerEvent = stateEngineEvent as Wayne.Lib.StateEngine.TimerEvent;
  64. if (timerEvent != null)
  65. {
  66. if (timerEvent.UserToken.Equals(myToken))
  67. {
  68. Timeout(ref transition);
  69. timerEvent.Handled = true;
  70. timer = null;
  71. }
  72. }
  73. }
  74. if (!stateEngineEvent.Handled)
  75. HandleNonTimeoutEvent(stateEngineEvent, ref transition);
  76. }
  77. /// <summary>
  78. /// See State.Exit
  79. /// </summary>
  80. protected override void Exit()
  81. {
  82. base.Exit();
  83. myToken = null;
  84. if (this.timer != null)
  85. {
  86. this.timer.Disable();
  87. this.timer = null;
  88. }
  89. }
  90. /// <summary>
  91. /// Method that is implemented by descendant classes to receive events that were not the timeout event.
  92. /// </summary>
  93. /// <param name="stateEngineEvent"></param>
  94. /// <param name="transition"></param>
  95. protected abstract void HandleNonTimeoutEvent(Wayne.Lib.StateEngine.StateEngineEvent stateEngineEvent, ref Wayne.Lib.StateEngine.Transition transition);
  96. /// <summary>
  97. /// Method that is used by descendant classes to set the timeout of the state.
  98. /// </summary>
  99. /// <returns></returns>
  100. protected abstract int TimeoutInterval { get;}
  101. /// <summary>
  102. /// Method that is used by descendant classes to be signaled when the timeout has fired.
  103. /// </summary>
  104. /// <param name="transition"></param>
  105. protected abstract void Timeout(ref Wayne.Lib.StateEngine.Transition transition);
  106. /// <summary>
  107. /// Cancels the currently running timer.
  108. /// </summary>
  109. protected void CancelTimer()
  110. {
  111. if (this.timer != null)
  112. {
  113. this.timer.Disable();
  114. this.timer = null;
  115. }
  116. }
  117. /// <summary>
  118. /// Restarts the timer. If a timer is active, it is restarted, and if the timer is not active anymore, it is started again.
  119. /// </summary>
  120. protected void ResetTimer()
  121. {
  122. CancelTimer();
  123. timer = new Wayne.Lib.StateEngine.Timer(this, GenericEventType.Timeout, TimeoutInterval, myToken);
  124. ActivateTimer(timer);
  125. }
  126. #endregion
  127. }
  128. }