Exemple #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 = this.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 (this.Owner != currentThread)
                {
                    while (inner != null)
                    {
                        if (inner.Owner == currentThread)
                        {
                            throw new LockOrderException("Unable to acquire lock {0} as lock {1} is already held",
                                                         this.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 this.count) == 1)
            {
                this.owner = Thread.CurrentThread;
            }
            return(ret);
        }
Exemple #2
0
 /// <summary>
 /// Sets the "inner" lock for this lock, returning this lock. This
 /// is a convenience method for setting InnerLock as part of a variable
 /// declaration.
 /// </summary>
 /// <example>
 /// OrderedLock inner = new OrderedLock();
 /// OrderedLock outer = new OrderedLock().SetInnerLock(inner);
 /// </example>
 /// <param name="inner">The inner </param>
 /// <returns>This lock is returned.</returns>
 public OrderedLock SetInnerLock(OrderedLock inner)
 {
     this.InnerLock = inner;
     return(this);
 }