コード例 #1
0
        /// <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="LockTimeoutException">The operation times out.</exception>
        /// <exception cref="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 LockToken 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 shortcutting,
            // 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;
                    }
                }
            }

            LockToken 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);
        }