| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.Runtime
- {
- using System;
- using System.Threading;
- [Fx.Tag.SynchronizationPrimitive(Fx.Tag.BlocksUsing.NonBlocking)]
- class SignalGate
- {
- [Fx.Tag.SynchronizationObject(Blocking = false, Kind = Fx.Tag.SynchronizationKind.InterlockedNoSpin)]
- int state;
- public SignalGate()
- {
- }
- internal bool IsLocked
- {
- get
- {
- return this.state == GateState.Locked;
- }
- }
- internal bool IsSignalled
- {
- get
- {
- return this.state == GateState.Signalled;
- }
- }
- // Returns true if this brings the gate to the Signalled state.
- // Transitions - Locked -> SignalPending | Completed before it was unlocked
- // Unlocked -> Signaled
- public bool Signal()
- {
- int lastState = this.state;
- if (lastState == GateState.Locked)
- {
- lastState = Interlocked.CompareExchange(ref this.state, GateState.SignalPending, GateState.Locked);
- }
- if (lastState == GateState.Unlocked)
- {
- this.state = GateState.Signalled;
- return true;
- }
- if (lastState != GateState.Locked)
- {
- ThrowInvalidSignalGateState();
- }
- return false;
- }
- // Returns true if this brings the gate to the Signalled state.
- // Transitions - SignalPending -> Signaled | return the AsyncResult since the callback already
- // | completed and provided the result on its thread
- // Locked -> Unlocked
- public bool Unlock()
- {
- int lastState = this.state;
- if (lastState == GateState.Locked)
- {
- lastState = Interlocked.CompareExchange(ref this.state, GateState.Unlocked, GateState.Locked);
- }
- if (lastState == GateState.SignalPending)
- {
- this.state = GateState.Signalled;
- return true;
- }
- if (lastState != GateState.Locked)
- {
- ThrowInvalidSignalGateState();
- }
- return false;
- }
- // This is factored out to allow Signal and Unlock to be inlined.
- void ThrowInvalidSignalGateState()
- {
- throw Fx.Exception.AsError(new InvalidOperationException(InternalSR.InvalidSemaphoreExit));
- }
- static class GateState
- {
- public const int Locked = 0;
- public const int SignalPending = 1;
- public const int Unlocked = 2;
- public const int Signalled = 3;
- }
- }
- [Fx.Tag.SynchronizationPrimitive(Fx.Tag.BlocksUsing.NonBlocking)]
- class SignalGate<T> : SignalGate
- {
- T result;
- public SignalGate()
- : base()
- {
- }
- public bool Signal(T result)
- {
- this.result = result;
- return Signal();
- }
- public bool Unlock(out T result)
- {
- if (Unlock())
- {
- result = this.result;
- return true;
- }
- result = default(T);
- return false;
- }
- }
- }
|