Пример #1
0
        /// <summary>
        /// Acquires the lock in shared mode, blocking
        /// if necessary.
        /// </summary>
        /// <remarks>
        /// Exclusive acquires are given precedence over shared
        /// acquires.
        /// </remarks>
        public void AcquireShared()
        {
            int value;
            int i = 0;

#if ENABLE_STATISTICS
            Interlocked.Increment(ref _acqShrdCount);
#endif
            while (true)
            {
                value = _value;

                // Case 1: lock not owned AND no exclusive waiter is waking up AND
                // there are no shared owners AND there are no exclusive waiters
                if ((value & (
                         LockOwned |
                         (LockSharedOwnersMask << LockSharedOwnersShift) |
                         ExclusiveMask
                         )) == 0)
                {
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockOwned + LockSharedOwnersIncrement,
                            value
                            ) == value)
                    {
                        break;
                    }
                }
                // Case 2: lock is owned AND no exclusive waiter is waking up AND
                // there are shared owners AND there are no exclusive waiters
                else if (
                    (value & LockOwned) != 0 &&
                    ((value >> LockSharedOwnersShift) & LockSharedOwnersMask) != 0 &&
                    (value & ExclusiveMask) == 0
                    )
                {
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockSharedOwnersIncrement,
                            value
                            ) == value)
                    {
                        break;
                    }
                }
                // Other cases.
                else if (i >= SpinCount)
                {
#if DEFER_EVENT_CREATION
                    this.EnsureEventCreated(ref _sharedWakeEvent);
#endif
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockSharedWaitersIncrement,
                            value
                            ) == value)
                    {
#if ENABLE_STATISTICS
                        Interlocked.Increment(ref _acqShrdSlpCount);

                        int shrdWtrsCount = (value >> LockSharedWaitersShift) & LockSharedWaitersMask;

                        Interlocked2.Set(
                            ref _peakShrdWtrsCount,
                            (p) => p < shrdWtrsCount,
                            (p) => shrdWtrsCount
                            );
#endif
                        // Go to sleep.
                        if (NativeMethods.WaitForSingleObject(
                                _sharedWakeEvent,
                                Timeout.Infinite
                                ) != NativeMethods.WaitObject0)
                        {
                            UtilsBreak("Utils.MsgFailedToWaitIndefinitely");
                        }

                        // Go back and try again.
                        continue;
                    }
                }

#if ENABLE_STATISTICS
                Interlocked.Increment(ref _acqShrdContCount);
#endif
                i++;
            }
        }
Пример #2
0
        /// <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;

                // Case 1: lock not owned AND an exclusive waiter is not waking up.
                // Here we don't have to check if there are exclusive waiters, because
                // if there are the lock would be owned, and we are checking that anyway.
                if ((value & (LockOwned | LockExclusiveWaking)) == 0)
                {
#if RIGOROUS_CHECKS
                    System.Diagnostics.Trace.Assert(((value >> LockSharedOwnersShift) & LockSharedOwnersMask) == 0);
                    System.Diagnostics.Trace.Assert(((value >> LockExclusiveWaitersShift) & LockExclusiveWaitersMask) == 0);
#endif
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockOwned,
                            value
                            ) == value)
                    {
                        break;
                    }
                }
                // Case 2: lock owned OR lock not owned and an exclusive waiter is waking up.
                // The second case means an exclusive waiter has just been woken up and is
                // going to acquire the lock. We have to go to sleep to make sure we don't
                // steal the lock.
                else if (i >= SpinCount)
                {
#if DEFER_EVENT_CREATION
                    // This call must go *before* the next operation. Otherwise,
                    // we will have a race condition between potential releasers
                    // and us.
                    this.EnsureEventCreated(ref _exclusiveWakeEvent);
#endif
                    if (Interlocked.CompareExchange(
                            ref _value,
                            value + LockExclusiveWaitersIncrement,
                            value
                            ) == value)
                    {
#if ENABLE_STATISTICS
                        Interlocked.Increment(ref _acqExclSlpCount);

                        int exclWtrsCount = (value >> LockExclusiveWaitersShift) & LockExclusiveWaitersMask;

                        Interlocked2.Set(
                            ref _peakExclWtrsCount,
                            (p) => p < exclWtrsCount,
                            (p) => exclWtrsCount
                            );
#endif
                        // Go to sleep.
                        if (NativeMethods.WaitForSingleObject(
                                _exclusiveWakeEvent,
                                Timeout.Infinite
                                ) != NativeMethods.WaitObject0)
                        {
                            UtilsBreak("Utils.MsgFailedToWaitIndefinitely");
                        }

                        // Acquire the lock.
                        // At this point *no one* should be able to steal the lock from us.
                        do
                        {
                            value = _value;
#if RIGOROUS_CHECKS
                            System.Diagnostics.Trace.Assert((value & LockOwned) == 0);
                            System.Diagnostics.Trace.Assert((value & LockExclusiveWaking) != 0);
#endif
                        } while(Interlocked.CompareExchange(
                                    ref _value,
                                    value + LockOwned - LockExclusiveWaking,
                                    value
                                    ) != value);

                        break;
                    }
                }

#if ENABLE_STATISTICS
                Interlocked.Increment(ref _acqExclContCount);
#endif
                i++;
            }
        }