/// <summary> /// Safely changes the current state /// </summary> /// <param name="newState">New state</param> /// <param name="prevState">Previously observed state</param> /// <returns>Was state changed (false means that the state transition is not valid)</returns> private bool ChangeStateSafe(QueueAsyncProcessorState newState, out QueueAsyncProcessorState prevState) { prevState = (QueueAsyncProcessorState)Volatile.Read(ref _state); if (!IsValidStateTransition(prevState, newState)) { return(false); } SpinWait sw = new SpinWait(); while (Interlocked.CompareExchange(ref _state, (int)newState, (int)prevState) != (int)prevState) { sw.SpinOnce(); prevState = (QueueAsyncProcessorState)Volatile.Read(ref _state); if (!IsValidStateTransition(prevState, newState)) { return(false); } } return(true); }
/// <summary> /// Verifies that state transition is possible /// </summary> /// <param name="oldState">Current state</param> /// <param name="newState">New state</param> /// <returns>True when state transition can be performed</returns> private bool IsValidStateTransition(QueueAsyncProcessorState oldState, QueueAsyncProcessorState newState) { switch (oldState) { case QueueAsyncProcessorState.Created: return(newState == QueueAsyncProcessorState.StartRequested || newState == QueueAsyncProcessorState.StopRequested); case QueueAsyncProcessorState.StartRequested: return(newState == QueueAsyncProcessorState.Running || newState == QueueAsyncProcessorState.Stopped); case QueueAsyncProcessorState.Running: return(newState == QueueAsyncProcessorState.StopRequested); case QueueAsyncProcessorState.StopRequested: return(newState == QueueAsyncProcessorState.Stopped); case QueueAsyncProcessorState.Stopped: return(false); default: return(false); } }