Пример #1
0
		public void InitialNoInnerLocks()
		{
			object monitor = new object();
			DateTime start = DateTime.UtcNow;
			for (int i=0; i < Iterations; i++)
			{
				lock (monitor)
				{
				}
			}
			DateTime end = DateTime.UtcNow;
			TimeSpan nativeTime = end-start;

			OrderedLock syncLock = new OrderedLock(Timeout.Infinite);

			start = DateTime.UtcNow;
			for (int i=0; i < Iterations; i++)
			{
				using (syncLock.Lock())
				{
				}
			}
			end = DateTime.UtcNow;
			TimeSpan syncLockTime = end-start;

			double factor = syncLockTime.TotalMilliseconds / nativeTime.TotalMilliseconds;

			Console.WriteLine ("Performance with no inner locks (initial acquisition):");
			Console.WriteLine ("Native: {0}", nativeTime);
			Console.WriteLine ("OrderedLock: {0}", syncLockTime);
			Console.WriteLine ("Performance penalty factor: {0:0.00}", factor);
			Console.WriteLine();

			Assert.IsTrue (factor < 10, "OrderedLock must not be ridiculously slow");
		}
Пример #2
0
		public void Setup()
		{
			subject = new OrderedLock("Test", Timeout.Infinite);

			inner1.InnerLock = inner2;
			subject.InnerLock = inner1;
		}
Пример #3
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);
        }
Пример #4
0
		public void AlreadyOwnedTwoInnerLocks()
		{
			DateTime start, end;

			object monitor = new object();
			
			lock (monitor)
			{
				start = DateTime.UtcNow;
				for	(int i=0; i < Iterations; i++)
				{
					lock (monitor)
					{
					}
				}
				end = DateTime.UtcNow;
			}
			TimeSpan nativeTime = end-start;

			OrderedLock orderedLock = new OrderedLock(Timeout.Infinite);
			OrderedLock inner1 = new OrderedLock(Timeout.Infinite);
			OrderedLock inner2 = new OrderedLock(Timeout.Infinite);
			orderedLock.InnerLock = inner1;
			inner1.InnerLock = inner2;

			using (orderedLock.Lock())
			{
				start = DateTime.UtcNow;
				for (int i=0; i < Iterations; i++)
				{
					using (orderedLock.Lock())
					{
					}
				}
				end = DateTime.UtcNow;
			}
			TimeSpan syncLockTime = end-start;
			double factor = syncLockTime.TotalMilliseconds / nativeTime.TotalMilliseconds;

			Console.WriteLine ("Performance with two inner locks (lock already owned):");
			Console.WriteLine ("Native: {0}", nativeTime);
			Console.WriteLine ("OrderedLock: {0}", syncLockTime);
			Console.WriteLine ("Performance penalty factor: {0:0.00}", factor);
			Console.WriteLine();

			Assert.IsTrue (factor < 10, "OrderedLock must not be ridiculously slow");
		}
Пример #5
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)
		{
			InnerLock = inner;
			return this;
		}
Пример #6
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)
 {
     InnerLock = inner;
     return(this);
 }