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;
            }
Beispiel #4
0
 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 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;
			}
			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;
    }