public void Release(short count) { while (true) { SemaphoreState currentState = GetCurrentState(); SemaphoreState newState = currentState; short remainingCount = count; // First, prefer to release existing spinners, // because a) they're hot, and b) we don't need a kernel // transition to release them. short spinnersToRelease = Math.Max((short)0, Math.Min(remainingCount, (short)(currentState.Spinners - currentState.CountForSpinners))); newState.CountForSpinners += spinnersToRelease; remainingCount -= spinnersToRelease; // Next, prefer to release existing waiters short waitersToRelease = Math.Max((short)0, Math.Min(remainingCount, (short)(currentState.Waiters - currentState.CountForWaiters))); newState.CountForWaiters += waitersToRelease; remainingCount -= waitersToRelease; // Finally, release any future spinners that might come our way newState.CountForSpinners += remainingCount; // Try to commit the transaction if (TryUpdateState(newState, currentState)) { // Now we need to release the waiters we promised to release if (waitersToRelease > 0) m_semaphore.Release(waitersToRelease); break; } } }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { SemaphoreState state = (SemaphoreState)value; switch (state) { case SemaphoreState.Green: return(Color.Green); break; case SemaphoreState.Yellow: return(Color.Yellow); break; case SemaphoreState.Red: return(Color.Red); break; default: return(Color.Black); break; } }
private SemaphoreState GetCurrentState() { // Volatile.Read of a long can get a partial read in x86 but the invalid // state will be detected in TryUpdateState with the CompareExchange. SemaphoreState state = new SemaphoreState(); state.RawData = Volatile.Read(ref m_state.RawData); return state; }
public void Reset() { Status = SemaphoreState.Off; Phase = 0; TlMode = SemaphoreMode.Manual; TlState = SemaphoreState.Off; TimeToChange = -1; CtrlType = SemaporeMaster.Unknown; LastUpdateUTC = DateTime.UtcNow; }
private bool TryUpdateState(SemaphoreState newState, SemaphoreState currentState) { if (Interlocked.CompareExchange(ref m_state.RawData, newState.RawData, currentState.RawData) == currentState.RawData) { Debug.Assert(newState.CountForSpinners <= MaxWorker, "CountForSpinners is greater than MaxWorker"); Debug.Assert(newState.CountForSpinners >= 0, "CountForSpinners is lower than zero"); Debug.Assert(newState.Spinners <= MaxWorker, "Spinners is greater than MaxWorker"); Debug.Assert(newState.Spinners >= 0, "Spinners is lower than zero"); Debug.Assert(newState.CountForWaiters <= MaxWorker, "CountForWaiters is greater than MaxWorker"); Debug.Assert(newState.CountForWaiters >= 0, "CountForWaiters is lower than zero"); Debug.Assert(newState.Waiters <= MaxWorker, "Waiters is greater than MaxWorker"); Debug.Assert(newState.Waiters >= 0, "Waiters is lower than zero"); Debug.Assert(newState.CountForSpinners + newState.CountForWaiters <= MaxWorker, "CountForSpinners + CountForWaiters is greater than MaxWorker"); return(true); } return(false); }
public bool Wait(TimeSpan timeout) { while (true) { SemaphoreState currentCounts = GetCurrentState(); SemaphoreState newCounts = currentCounts; // First, just try to grab some count. if (currentCounts.CountForSpinners > 0) { --newCounts.CountForSpinners; if (TryUpdateState(newCounts, currentCounts)) { return(true); } } else { // No count available, become a spinner ++newCounts.Spinners; if (TryUpdateState(newCounts, currentCounts)) { break; } } } // // Now we're a spinner. // int numSpins = 0; const int spinLimitPerProcessor = 50; while (true) { SemaphoreState currentCounts = GetCurrentState(); SemaphoreState newCounts = currentCounts; if (currentCounts.CountForSpinners > 0) { --newCounts.CountForSpinners; --newCounts.Spinners; if (TryUpdateState(newCounts, currentCounts)) { return(true); } } else { double spinnersPerProcessor = (double)currentCounts.Spinners / ProcessorCount; int spinLimit = (int)((spinLimitPerProcessor / spinnersPerProcessor) + 0.5); if (numSpins >= spinLimit) { --newCounts.Spinners; ++newCounts.Waiters; if (TryUpdateState(newCounts, currentCounts)) { break; } } else { // // We yield to other threads using Thread.Sleep(0) rather than the more traditional Thread.Yield(). // This is because Thread.Yield() does not yield to threads currently scheduled to run on other // processors. On a 4-core machine, for example, this means that Thread.Yield() is only ~25% likely // to yield to the correct thread in some scenarios. // Thread.Sleep(0) has the disadvantage of not yielding to lower-priority threads. However, this is ok because // once we've called this a few times we'll become a "waiter" and wait on the Semaphore, and that will // yield to anything that is runnable. // Thread.Sleep(0); numSpins++; } } } // // Now we're a waiter // bool waitSucceeded = m_semaphore.WaitOne(timeout); while (true) { SemaphoreState currentCounts = GetCurrentState(); SemaphoreState newCounts = currentCounts; --newCounts.Waiters; if (waitSucceeded) { --newCounts.CountForWaiters; } if (TryUpdateState(newCounts, currentCounts)) { return(waitSucceeded); } } }
private bool TryUpdateState(SemaphoreState newState, SemaphoreState currentState) { if (Interlocked.CompareExchange(ref m_state.RawData, newState.RawData, currentState.RawData) == currentState.RawData) { Debug.Assert(newState.CountForSpinners <= MaxWorker, "CountForSpinners is greater than MaxWorker"); Debug.Assert(newState.CountForSpinners >= 0, "CountForSpinners is lower than zero"); Debug.Assert(newState.Spinners <= MaxWorker, "Spinners is greater than MaxWorker"); Debug.Assert(newState.Spinners >= 0, "Spinners is lower than zero"); Debug.Assert(newState.CountForWaiters <= MaxWorker, "CountForWaiters is greater than MaxWorker"); Debug.Assert(newState.CountForWaiters >= 0, "CountForWaiters is lower than zero"); Debug.Assert(newState.Waiters <= MaxWorker, "Waiters is greater than MaxWorker"); Debug.Assert(newState.Waiters >= 0, "Waiters is lower than zero"); Debug.Assert(newState.CountForSpinners + newState.CountForWaiters <= MaxWorker, "CountForSpinners + CountForWaiters is greater than MaxWorker"); return true; } return false; }
void ProceedState(SemaphoreState state) { switch(state) { case SemaphoreState.E_INVISIBLE: { for(var i = 0; i < Lights.Count; ++i) { if(Lights[i] != null) { Lights[i].SetLightState(CP_SemaphoreLight.LightState.E_DISABLED); } } break; } case SemaphoreState.E_WAITING: { _stateStartTime = TimeUtils.TimestampMilliseconds; _stateRandomTime = 1000; break; } case SemaphoreState.E_SHOWING: { for(var i = 0; i < Lights.Count; ++i) { if(Lights[i] != null) { Lights[i].SetLightState(CP_SemaphoreLight.LightState.E_OFF); } } _stateStartTime = TimeUtils.TimestampMilliseconds; _stateRandomTime = 1000; break; } case SemaphoreState.E_P1: { Lights[0].SetLightState(CP_SemaphoreLight.LightState.E_RED); _stateStartTime = TimeUtils.TimestampMilliseconds; _stateRandomTime = 1250; break; } case SemaphoreState.E_P2: { Lights[1].SetLightState(CP_SemaphoreLight.LightState.E_RED); _stateStartTime = TimeUtils.TimestampMilliseconds; _stateRandomTime = 1250; break; } case SemaphoreState.E_P3: { Lights[2].SetLightState(CP_SemaphoreLight.LightState.E_RED); _stateStartTime = TimeUtils.TimestampMilliseconds; _stateRandomTime = 1250; break; } case SemaphoreState.E_P4: { Lights[0].SetLightState(CP_SemaphoreLight.LightState.E_GREEN); Lights[1].SetLightState(CP_SemaphoreLight.LightState.E_GREEN); Lights[2].SetLightState(CP_SemaphoreLight.LightState.E_GREEN); Lights[3].SetLightState(CP_SemaphoreLight.LightState.E_GREEN); _stateStartTime = TimeUtils.TimestampMilliseconds; _stateRandomTime = 1500; if(_sceneManager != null) { _sceneManager.SetCurrentGameState(CP_SceneManager.BattleState.E_PLAYING); } break; } } CurrentsemaphoreState = state; }