private bool IsValidStateTransition(StableConnectionState oldState, StableConnectionState newState) { switch (oldState) { case StableConnectionState.Created: return newState == StableConnectionState.Opening || newState == StableConnectionState.Closed; case StableConnectionState.Opening: return newState == StableConnectionState.Opened || newState == StableConnectionState.Closed; case StableConnectionState.Opened: return newState == StableConnectionState.Closed; case StableConnectionState.Closed: return newState == StableConnectionState.Invalid; case StableConnectionState.Invalid: return false; default: throw new InvalidProgramException("Unknown StableConnectionState value: " + oldState.ToString()); } }
private StableConnectionState ChangeStateSafe(StableConnectionState newState) { var curState = _state; if (!IsValidStateTransition((StableConnectionState)curState, newState)) return (StableConnectionState)curState; if (Interlocked.CompareExchange(ref _state, (int)newState, curState) == curState) return (StableConnectionState)curState; SpinWait sw = new SpinWait(); while (Interlocked.CompareExchange(ref _state, (int)newState, curState) != curState) { sw.SpinOnce(); curState = _state; if (!IsValidStateTransition((StableConnectionState)curState, newState)) return (StableConnectionState)curState; } return (StableConnectionState)curState; }