コード例 #1
0
        /// <inheritdoc />
        /// <summary>
        /// Locks the monitor, with the specified timeout. This implementation validates
        /// the ordering of locks, and maintains the current owner.
        /// </summary>
        /// <param name="timeout">
        /// The timeout, in milliseconds. Must be Timeout.INFINITE,
        /// or non-negative.
        /// </param>
        /// <returns>A lock token which should be disposed to release the lock</returns>
        /// <exception cref="T:essentialMix.Exceptions.LockTimeoutException">The operation times out.</exception>
        /// <exception cref="T:essentialMix.Exceptions.LockOrderException">
        /// The lock order would be violated if this lock were taken out. (i.e. attempting
        /// to acquire the lock could cause deadlock.)
        /// </exception>
        public override IDisposable Lock(int timeout)
        {
            // Check whether we should be allowed to take out this lock, according to
            // the inner locks we have.
            // Performance note: This would be in a separate method, but the cost of
            // making a method call (which can't be inlined in this case) is sufficiently
            // high as to make it worth manually inlining.
            OrderedLock inner = InnerLock;

            // Performance note: This would be a single if statement with shortcut,
            // but fetching the current thread is mildly expensive.

            if (inner != null)
            {
                Thread currentThread = Thread.CurrentThread;

                if (Owner != currentThread)
                {
                    while (inner != null)
                    {
                        if (inner.Owner == currentThread)
                        {
                            throw new LockOrderException("Unable to acquire lock {0} as lock {1} is already held", Name, inner.Name);
                        }
                        inner = inner.InnerLock;
                    }
                }
            }

            IDisposable ret = base.Lock(timeout);

            // Now remember that we've locked, and set the owner if necessary
            // Performance note: On a single processor, it is slightly cheaper
            // to assign owner every time, without a test. On multiple processor
            // boxes, it is cheaper to avoid the volatile write.
            if (Interlocked.Increment(ref _count) == 1)
            {
                Owner = Thread.CurrentThread;
            }
            return(ret);
        }
コード例 #2
0
 public OrderedLock SetInnerLock(OrderedLock inner)
 {
     InnerLock = inner;
     return(this);
 }