Пример #1
0
 private void TransitionToSynchronized(QState targetState, ref TransitionChain transitionChain)
 {
     //The entire method had been embedded within [MethodImpl(MethodImplOptions.Synchronized)],
     //which is not available in .NET Core, and so a lock is used instead...
     lock (this)
     {
         if (transitionChain != null)
         {
             // We encountered a race condition. The first (non-synchronized) check indicated that the transition chain
             // is null. However, a second threat beat us in getting into this synchronized method and populated
             // the transition chain in the meantime. We can execute the regular method again now.
             TransitionTo(targetState, ref transitionChain);
         }
         else
         {
             // The transition chain is not initialized yet, we need to dynamically retrieve
             // the required transition steps and record them so that we can subsequently simply
             // play them back.
             TransitionChainRecorder recorder = new TransitionChainRecorder();
             TransitionFromSourceToTarget(targetState.GetMethodInfo(), recorder);
             // We pass the recorded transition steps back to the caller:
             transitionChain = recorder.GetRecordedTransitionChain();
         }
     }
 }
Пример #2
0
            /// <summary>
            /// Reallocates the internal array <see cref="m_Items"/> to an array twice the previous capacity.
            /// </summary>
            private void IncreaseCapacity()
            {
                int newCapacity;

                if (m_Items.Length == 0)
                {
                    newCapacity = c_DefaultCapacity;
                }
                else
                {
                    newCapacity = m_Items.Length * 2;
                }
                TransitionChain[] newItems = new TransitionChain[newCapacity];
                Array.Copy(m_Items, 0, newItems, 0, m_Items.Length);
                m_Items = newItems;
            }
Пример #3
0
        /// <summary>
        /// Performs the transition from the current state to the specified target state.
        /// </summary>
        /// <param name="targetState">The <see cref="QState"/> to transition to.</param>
        /// <param name="transitionChain">A <see cref="TransitionChain"/> used to hold the transition chain that
        /// needs to be executed to perform the transition to the target state.</param>
        /// <remarks>
        /// The very first time that a given static transition is executed, the <see paramref="transitionChain"/>
        /// reference will point to <see langword="null"/>. In this case a new <see cref="TransitionChain"/>
        /// instance is created. As the complete transition is performed the individual transition steps are
        /// recorded in the new <see cref="TransitionChain"/> instance. At the end of the call the new
        /// (and now filled) <see cref="TransitionChain"/> is handed back to the caller.
        /// If the same transition needs to be performed later again, the caller needs to pass
        /// in the filled <see cref="TransitionChain"/> instance. The recorded transition path will then be
        /// played back very efficiently.
        /// </remarks>
        protected void TransitionTo(QState targetState, ref TransitionChain transitionChain)
        {
            Debug.Assert(targetState != s_TopState);             // can't target 'top' state
            ExitUpToSourceState();

            if (transitionChain == null)             // for efficiency the first check is not thread-safe
            {
                // We implement the double-checked locking pattern
                TransitionToSynchronized(targetState, ref transitionChain);
            }
            else
            {
                // We just need to 'replay' the transition chain that is stored in the transitions chain.
                ExecuteTransitionChain(transitionChain);
            }
        }
Пример #4
0
        private void ExecuteTransitionChain(TransitionChain transitionChain)
        {
            // There must always be at least one transition step in the provided transition chain
            Debug.Assert(transitionChain.Length > 0);

            TransitionStep transitionStep = transitionChain[0];             // to shut up the compiler;

            // without it we would get the following error on the line
            //       m_MyState = transitionStep.State;
            // at the end of this method: Use of possibly unassigned field 'State'
            for (int i = 0; i < transitionChain.Length; i++)
            {
                transitionStep = transitionChain[i];
                Trigger(transitionStep.State, transitionStep.QSignal);
            }
            m_MyState = transitionStep.State;
        }
Пример #5
0
 private void TransitionToSynchronized(QState targetState, ref TransitionChain transitionChain)
 {
     if (transitionChain != null)
     {
         // We encountered a race condition. The first (non-synchronized) check indicated that the transition chain
         // is null. However, a second threat beat us in getting into this synchronized method and populated
         // the transition chain in the meantime. We can execute the regular method again now.
         TransitionTo(targetState, ref transitionChain);
     }
     else
     {
         // The transition chain is not initialized yet, we need to dynamically retrieve
         // the required transition steps and record them so that we can subsequently simply
         // play them back.
         TransitionChainRecorder recorder = new TransitionChainRecorder();
         TransitionFromSourceToTarget(targetState, recorder);
         // We pass the recorded transition steps back to the caller:
         transitionChain = recorder.GetRecordedTransitionChain();
     }
 }
Пример #6
0
 private void EnsureLastTransistionStepIsEntryIntoTargetState(
     QState targetState,
     TransitionChainRecorder recorder)
 {
     if (recorder.GetRecordedTransitionChain().Length == 0)
     {
         // Nothing recorded so far
         RecordEntryIntoTargetState(targetState, recorder);
         return;
     }
     else
     {
         // We need to test whether the last recorded transition step is the entry into the target state
         TransitionChain transitionChain    = recorder.GetRecordedTransitionChain();
         TransitionStep  lastTransitionStep = transitionChain[transitionChain.Length - 1];
         if (lastTransitionStep.State != targetState ||
             lastTransitionStep.QSignal != QSignals.Entry)
         {
             RecordEntryIntoTargetState(targetState, recorder);
             return;
         }
     }
 }
 /// <summary>
 /// Creates a TransitionChain and runs it.
 /// </summary>
 public static void runChain(params Transition[] transitions)
 {
     TransitionChain chain = new TransitionChain(transitions);
 }
Пример #8
0
 /// <summary>
 /// Should be called once all required slots have been established in order to minimize the memory
 /// footprint of the store.
 /// </summary>
 public void ShrinkToActualSize()
 {
     TransitionChain[] newItems = new TransitionChain[m_Size];
     Array.Copy(m_Items, 0, newItems, 0, m_Size);
     m_Items = newItems;
 }
Пример #9
0
 /// <summary>
 /// Reallocates the internal array <see cref="m_Items"/> to an array twice the previous capacity.
 /// </summary>
 private void IncreaseCapacity()
 {
     int newCapacity;
     if (m_Items.Length == 0)
     {
         newCapacity = c_DefaultCapacity;
     }
     else
     {
         newCapacity	= m_Items.Length * 2;
     }
     TransitionChain[] newItems = new TransitionChain[newCapacity];
     Array.Copy(m_Items, 0, newItems, 0, m_Items.Length);
     m_Items = newItems;
 }
Пример #10
0
 /// <summary>
 /// Should be called once all required slots have been established in order to minimize the memory 
 /// footprint of the store.
 /// </summary>
 public void ShrinkToActualSize()
 {
     TransitionChain[] newItems = new TransitionChain[m_Size];
     Array.Copy(m_Items, 0, newItems, 0, m_Size);
     m_Items = newItems;
 }
Пример #11
0
 private void TransitionToSynchronized(QState targetState, ref TransitionChain transitionChain)
 {
     if (transitionChain != null)
     {
         // We encountered a race condition. The first (non-synchronized) check indicated that the transition chain
         // is null. However, a second threat beat us in getting into this synchronized method and populated
         // the transition chain in the meantime. We can execute the regular method again now.
         TransitionTo(targetState, ref transitionChain);
     }
     else
     {
         // The transition chain is not initialized yet, we need to dynamically retrieve
         // the required transition steps and record them so that we can subsequently simply
         // play them back.
         TransitionChainRecorder recorder = new TransitionChainRecorder();
         TransitionFromSourceToTarget(targetState.Method, recorder);
         // We pass the recorded transition steps back to the caller:
         transitionChain = recorder.GetRecordedTransitionChain();
     }
 }
Пример #12
0
        private void ExecuteTransitionChain(TransitionChain transitionChain)
        {
            // There must always be at least one transition step in the provided transition chain
            Debug.Assert(transitionChain.Length > 0);

            TransitionStep transitionStep = transitionChain[0]; // to shut up the compiler;
            // without it we would get the following error on the line
            //       m_MyStateMethod = transitionStep.StateMethod;
            // at the end of this method: Use of possibly unassigned field 'State'
            for(int i = 0; i < transitionChain.Length; i++)
            {
                transitionStep = transitionChain[i];
                Trigger(transitionStep.StateMethod, transitionStep.QSignal);
            }
            m_MyStateMethod = transitionStep.StateMethod;
        }
Пример #13
0
        /// <summary>
        /// Performs the transition from the current state to the specified target state.
        /// </summary>
        /// <param name="targetState">The <see cref="QState"/> to transition to.</param>
        /// <param name="transitionChain">A <see cref="TransitionChain"/> used to hold the transition chain that
        /// needs to be executed to perform the transition to the target state.</param>
        /// <remarks>
        /// The very first time that a given static transition is executed, the <see paramref="transitionChain"/> 
        /// reference will point to <see langword="null"/>. In this case a new <see cref="TransitionChain"/> 
        /// instance is created. As the complete transition is performed the individual transition steps are 
        /// recorded in the new <see cref="TransitionChain"/> instance. At the end of the call the new 
        /// (and now filled) <see cref="TransitionChain"/> is handed back to the caller.
        /// If the same transition needs to be performed later again, the caller needs to pass 
        /// in the filled <see cref="TransitionChain"/> instance. The recorded transition path will then be 
        /// played back very efficiently.
        /// </remarks>
        protected void TransitionTo(QState targetState, ref TransitionChain transitionChain)
        {
            Debug.Assert(targetState != s_TopState); // can't target 'top' state
            ExitUpToSourceState();

            if (transitionChain == null) // for efficiency the first check is not thread-safe
            {
                // We implement the double-checked locking pattern
                TransitionToSynchronized(targetState, ref transitionChain);
            }
            else
            {
                // We just need to 'replay' the transition chain that is stored in the transitions chain.
                ExecuteTransitionChain(transitionChain);
            }
        }
Пример #14
0
 public static void runChain(params Transition[] transitions)
 {
     TransitionChain transitionChain = new TransitionChain(transitions);
 }