internal SpinLockContext(SpinLock spinLock) { _spinLock = spinLock; _spinLock.Acquire(); _disposed = false; }
/// <summary> /// Acquires the lock in exclusive mode, blocking /// if necessary. /// </summary> /// <remarks> /// Exclusive acquires are given precedence over shared /// acquires. /// </remarks> public void AcquireExclusive() { int value; int i = 0; #if ENABLE_STATISTICS Interlocked.Increment(ref _acqExclCount); #endif while (true) { value = _value; // Try to obtain the lock. if ((value & LockOwned) == 0) { #if RIGOROUS_CHECKS System.Diagnostics.Trace.Assert(((value >> LockSharedOwnersShift) & LockSharedOwnersMask) == 0); #endif if (Interlocked.CompareExchange( ref _value, value + LockOwned, value ) == value) { break; } } else if (i >= _spinCount) { // We need to wait. WaitBlock waitBlock; waitBlock.Flags = WaiterExclusive | WaiterSpinning; // Obtain the waiters list lock. _lock.Acquire(); try { // Try to set the waiters bit. if (Interlocked.CompareExchange( ref _value, value | LockWaiters, value ) != value) { #if ENABLE_STATISTICS Interlocked.Increment(ref _insWaitBlkRetryCount); #endif // Unfortunately we have to go back. This is // very wasteful since the waiters list lock // must be released again, but must happen since // the lock may have been released. continue; } // Put our wait block behind other exclusive waiters but // in front of all shared waiters. this.InsertWaitBlock(&waitBlock, ListPosition.LastExclusive); #if ENABLE_STATISTICS _exclusiveWaitersCount++; if (_peakExclWtrsCount < _exclusiveWaitersCount) { _peakExclWtrsCount = _exclusiveWaitersCount; } #endif } finally { _lock.Release(); } #if ENABLE_STATISTICS Interlocked.Increment(ref _acqExclBlkCount); #endif this.Block(&waitBlock); // Go back and try again. continue; } #if ENABLE_STATISTICS Interlocked.Increment(ref _acqExclContCount); #endif i++; } }