|
using System;
namespace RTLib
{
/// <summary>
/// RTLib is a .NET class library to deal with threads, events and finite state machines (FSMs).
/// Features:
/// <list>
/// <para>- Supports multi-threading</para>
/// <para>- Supports multiple FSMs on one thread</para>
/// <para>- Supports timer events</para>
/// <para>- Allows definition of transition handlers AND / or an event handlers</para>
/// <para>- Supports state entry and exit handlers</para>
/// <para>- Allows definition default transition and event handlers</para>
/// <para>- Minimal effort to write an FSM, less code</para>
/// <para>- Flexible through optional usage of attributes</para>
/// <para>- Allows one-to-one translation from UML state diagrams</para>
/// </list>
/// <para>During startup, RTLib uses reflection to inspect the user defined classes and creates
/// event dispatching tables and the bindings to the user-defined handler functions.</para>
///
/// <para>Implementing an FSM, Step by Step:</para>
/// <para>1. Derive a class from the RTLib base class Fsm.</para>
/// <para> Add a state enumeration type and a state member.</para>
/// <para> Override the GetCurrentState method.</para>
/// <para> Initialize state with the initial state:</para>
///<code>
///public class MyFsm : RTLib.Fsm
///{
/// public enum MyState
/// {
/// MyState1,
/// MyState2,
/// MyState3
/// };
///
/// public MyFsm ()
/// {
/// state = MyState.MyState1;
/// }
///
/// private MyState state;
///
/// override protected int GetCurrentState()
/// {
/// return (int)state;
/// }
///}
///</code>
///<remarks>
///The only reason for GetCurrentState() is, that the Fsm class get to know the current state. I did not find a way create it automatically by reflection.
///</remarks>
///<para>2. Define your event classes. Every event type is a class derived from the base
///class FsmEvent. There exist special event base classes for timer events
///and synchronizable events.
///Even it is possible to define them public, they are usually
///private to your Fsm as nested classes. Examples:</para>
///<code>
///private class MyEvent : RTLib.FsmEvent
///{
/// public MyEvent()
/// {
/// }
///}
///
///private class MyEventWithParam : RTLib.FsmEvent
///{
/// public MyEventWithParam(Param1Type param1)
/// {
/// m_Param1 = param1
/// }
///
/// public Param1Type Param1
/// {
/// get { return m_Param1;}
/// }
///
/// private Param1Type m_Param1;
///}
///
///private class MyTimerEvent : FsmTimerEvent
///{
/// public MyEventA() : base( new TimeSpan(0,0,6) ) // 6 sec
/// {
/// }
///}
///
///private class MyAbsoluteTimerEvent : FsmTimerEvent
///{
/// public MyEventA()
/// : base( new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
/// 12, 0, 0) ) // Today at noon (12:00:00)
/// {
/// }
///}
///</code>
///
///<para>3. Define your transition-, event- and state handlers.</para>
///
///<para>Transition Handler:</para>
///<para>A method, which is called upon receiving a specific event in a certain state.
///Either you can use the naming convention State_Xxxxx(MyEvent) or you can define
///a method attribute [FsmTransitionHandler("State")].</para>
///<para>If you define a transition handler with a event parameter of the base event
///class FsmEvent, it is a default transition handler for this state. This can be
///used to implement default handling for unexpected events.</para>
///
///<para>Event Handler:</para>
///A method, which is called upon receiving a specific event in an FSM without
///states or with no transition handler for this event and the current state.
///Either you can use the naming convention Xxxxx(MyEvent) or you can define a
///method attribute [FsmEventHandler].
///
///<para>State Handler:</para>
///A method, which is called upon entering or exit a certain state. Either you
///can use the naming convention State_EntryState(), respective State_ExitState()
///or you can define a method attribute [FsmStateHandler("State", EStateHandlerType.Entry )],
///respective [FsmStateHandler("State", EStateHandlerType.Exit )].
///
///Important note: Attributes can be used only if your FSM class has the following
///attribute: [FsmCoding(ECodingType.WithAttributes)]. If you want to suppress
///resolution of the naming convention in an FSM without attribute usage, you can
///use the method attribute [FsmNoHandler] for any kind of handler method.
///
///<para>Examples:</para>
///<code>
/// // A transition handler
///private void MyState1_OnMyEventWithParam( MyEventWithParam ev )
///{
/// Trace.Write(DateTime.Now+" "+GetType().Name+": ");
/// Trace.Write("MyState1_OnMyEventWithParam, Param = ");
/// Trace.WriteLine(ev.Param1);
/// state = MyState.MyState2;
///}
///
/// // A transition handler with attribute
///[FsmTransitionHandler("MyState1")]
///private void TransitionHandlerWithAttribute( MyEvent ev )
///{
/// Trace.Write(DateTime.Now+" "+GetType().Name+": ");
/// Trace.Write("TransitionhandlerWithAttribute");
/// state = MyState.MyState2;
///}
///
/// // A state handler
///private void MyState1_EntryState( FsmEvent ev, State oldState)
///{
/// Trace.Write(DateTime.Now+" "+GetType().Name+": ");
/// Trace.WriteLine("MyState1_EntryState, oldState = "+oldState.ToString() );
///}
///
/// // An event handler
///private void OnMyEventWithParam( MyEvent ev )
///{
/// Trace.Write(DateTime.Now+" "+GetType().Name+": ");
/// Trace.WriteLine("OnMyEvent");
///}
///</code>
///
///4. Create an FsmProcessor object and push the FSM to it. If you want to
///syncronize to completion of the FSM, add also a Wait() call:
///<code>
///FsmProcessor processor = new FsmProcessor("MyProc");
///MyFsm myFsm = new MyFsm();
///processor.PushFsm(myFsm);
///myFsm.Wait();
///</code>
///Note: With Wait() it is also possible to synchronize to the
///processing of a posted event if it is derived from SyncEvent.
///Fsm and EventBase have a constructor with a synchronized parameter.
///
///<para>5. There are several ways to terminate the FSM:</para>
///
///<para>FSM Internally:</para>
///<para>In any handler, call the base method TerminateFsm()</para>
///
///<para>FSM Externally and FSM Internally:</para>
///<para>Call Terminate() on Fsm or TerminateFsm(Fsm)on FsmProcessor</para>
///
///<para>FSM Externally:</para>
///<para>Call TerminateAllFsm(delay) on FsmProcessor</para>
///
///<para>FSM Entry and Exit Code:</para>
///When an FSM is posted the thread associated with the FSM processor calls
///first the override method OnFsmEntry(). When an FSM terminates
///the thread associated with the FSM processor calls the override method OnFsmExit()
///just before the FSM object is deleted.
///By overriding these methods, the user has a
///chance to execute some initialization and clean-up code in the context of the
///FSM processor thread the FSM is executing on.
///
///<para>Event Processing:</para>
///For performance reasons, all time consuming reflection code is done at start-up time.
///At runtime, just a few look-ups are necessary to find and call the right handler method.
///An FSM can have a state variable or not. This has influence to the event
///handling. With states, the FSM handles the event in the following order:
///<para>With states:</para>
///<list>
///<para>Try to dispatch the event to a transition handler</para>
///<para>If not existing, try to dispatch the event to a default transition handler</para>
///<para>If not existing, try to dispatch the event to a event handler</para>
///<para>If not existing, call the default event handler</para>
///<para>If not overridden, output an error trace</para>
///</list>
///<para>Without states:</para>
///<list>
///<para>If not existing, try to dispatch the event to a event handler</para>
///<para>If not existing, call the default event handler</para>
///<para>If not overridden, output an error trace</para>
///</list>
///</summary>
public class NamespaceDoc
{
public NamespaceDoc()
{
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.