/// <summary>
 /// Set up the cache.
 /// </summary>
 static DescriptionResolver()
 {
     _cachePadlock = new Padlock();
     _cache = new ThreadShared<Dictionary<string, Dictionary<string, string>>>(
         new Dictionary<string, Dictionary<string, string>>(),
         _cachePadlock);
 }
		public void Constructor_OtherPadlockNull()
		{
			Padlock p1 = new Padlock();
			Padlock p2 = null;
			Padlock p3 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1, p2, p3);
		}
		/// <summary>
		/// Called from a Padlock when the padlock is locked.
		/// </summary>
		/// <param name="plock">
		/// The padlock that is attempting to start protection of this resource.
		/// </param>
		internal void StartProtection(Padlock plock)
		{
			lock (_internalStateLock)
			{
				EnsureLockIsAssociatedWithThisResource(plock);

				_associatedPadlocks[plock]++;
			}
		}
		public void Constructor_ConstructWithValueType()
		{
			Padlock p = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(10, p);

			using (p.Lock())
			{
				Assert.AreEqual(i.Value, 10);
			}
		}
		public void Constructor_ConstructWithReferenceType()
		{
			Padlock p = new Padlock();

			//Uri is a random reference type;
			ThreadShared<Uri> i = new ThreadShared<Uri>(new Uri("http://example.com"), p);

			using (p.Lock())
			{
				Assert.AreEqual(i.Value, new Uri("http://example.com"));
			}
		}
		/// <summary>
		/// Creates a new ThreadShared resource
		/// </summary>
		/// <param name="firstMandatoryLock">
		/// All ThreadShared resources MUST be associated with at least 1 lock
		/// </param>
		/// <param name="otherLocks">
		/// Some resources need to be protected by more than 1 lock, specify
		/// all the other padlocks that protect this resource here.
		/// </param>
		/// <exception cref="System.ArgumentNullException">
		/// Thrown if FirstMandatorLock is null
		/// </exception>
		protected BaseThreadShared(Padlock firstMandatoryLock, params Padlock[] otherLocks)
		{
			Insist.IsNotNull(firstMandatoryLock, "firstMandatoryLock");
			Insist.AllItemsAreNotNull(otherLocks, "otherLocks");

			_associatedPadlocks = new Dictionary<Padlock, int>();
			_associatedPadlocks.Add(firstMandatoryLock, 0);

			foreach (Padlock currentPadlock in otherLocks)
			{
				_associatedPadlocks.Add(currentPadlock, 0);
			}

			//Register this ThreadShared resource with all of the associated Padlocks.
			foreach (Padlock currentPadlock in _associatedPadlocks.Keys)
			{
				currentPadlock.Register(this);
			}
		}
		private void RecursiveFunction(int maxRecursionDepth, int currentDepth, Padlock p, ThreadShared<int> i)
		{
			if (currentDepth < maxRecursionDepth)
			{
				using (p.Lock())
				{
					i.Value++;
					RecursiveFunction(maxRecursionDepth, ++currentDepth, p, i);
				}
			}
		}
		public void LockTakenRecursively()
		{
			Padlock p1 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1);
			RecursiveFunction(5, 0, p1, i);

			using (p1.Lock())
			{
				Assert.AreEqual(i.Value, 5);
			}
		}
		public void TwoLocksBothTaken()
		{
			Padlock p1 = new Padlock();
			Padlock p2 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1, p2);

			using (p1.Lock())
			{
				using (p2.Lock())
				{
					i.Value++;
					Assert.AreEqual(i.Value, 1);
				}
			}
		}
		/// <summary>
		/// Ensures that the supplied Padlock is associated with this protected resource.
		/// </summary>	
		/// <exception cref="System.ArgumentException">
		/// Thrown if the supplied padlock is not associated with this resource.
		/// </exception>
		private void EnsureLockIsAssociatedWithThisResource(Padlock plock)
		{
			//MAKE SURE THAT _internalStateLock IS TAKEN BEFORE CALLING THIS METHOD

			if (!_associatedPadlocks.Keys.Contains(plock))
			{
				throw new ArgumentException("This resource is not protected by this lock");
			}
		}
		public void Constructor_AllPadlocksValid()
		{
			Padlock p1 = new Padlock();
			Padlock p2 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1, p2);
		}
		public void Constructor_ConstructWithName()
		{
			Padlock p1 = new Padlock("PadlockX");
			Assert.IsTrue(p1.Name.Equals("PadlockX"));
		}
		public void Constructor_ConstructWithNoName()
		{
			Padlock p1 = new Padlock();
			Assert.IsTrue(p1.Name.StartsWith("Padlock-"));
		}
		/// <summary>
		/// Initialize the random number generator
		/// </summary>
		static StaticRandom()
		{
			_padlock = new Padlock();
			_random = new ThreadShared<Random>(new Random(), _padlock);
		}
		public void OnePadlockToMultipleResources()
		{
			Padlock p1 = new Padlock();
			ThreadShared<int> i1 = new ThreadShared<int>(0, p1);
			ThreadShared<int> i2 = new ThreadShared<int>(0, p1);

			//Can access both ThreadShared in same block...
			using (p1.Lock())
			{
				i1.Value++;
				i2.Value++;
			}

			//... or individually
			using (p1.Lock())
			{
				i1.Value++;
			}

			using (p1.Lock())
			{
				i2.Value++;
			}

			using(p1.Lock())
			{
				Assert.AreEqual(i1.Value, 2);
				Assert.AreEqual(i2.Value, 2);
				Assert.AreEqual(i1.Value, i2.Value);
			}
		}
		public void ExceptionThrownWhileLockHeld()
		{
			Padlock p1 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1);

			try
			{
				using (p1.Lock())
				{
					i.Value++;
					throw new InvalidOperationException();
				}
			}
			catch (InvalidOperationException) {	}

			//Locks should have been released.  Create a new thread
			//to obtain the lock to ensure no deadlocks ensue.

			Thread secondThread = new Thread(delegate()
				{
					using (p1.Lock())
					{
						i.Value++;
					}
				});

			secondThread.Start();
			secondThread.Join();

			using (p1.Lock())
			{
				Assert.AreEqual(i.Value, 2);
			}
		}
		public void OneLockNotTaken()
		{
			Padlock p1 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1);

			//Access value outside of lock.
			i.Value++;
		}
		public void OneLockTaken()
		{
			Padlock p1 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1);

			using (p1.Lock())
			{
				i.Value++;
				Assert.AreEqual(i.Value, 1);
			}
		}
		public void TwoLocksSecondNotTaken()
		{
			Padlock p1 = new Padlock();
			Padlock p2 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1, p2);

			//Access value outside of both locks.
			using (p1.Lock())
			{
				i.Value++;
			}
		}
		public void ValueGettersAreEqual()
		{
			Padlock p1 = new Padlock();
			ThreadShared<int> i = new ThreadShared<int>(0, p1);

			using (p1.Lock())
			{
				Assert.AreEqual(i.Value, i._);
				i.Value++;

				Assert.AreEqual(i.Value, i._);
				Assert.AreEqual(i.Value, 1);
				Assert.AreEqual(i._, 1);

				i._++;
				Assert.AreEqual(i.Value, i._);
				Assert.AreEqual(i.Value, 2);
				Assert.AreEqual(i._, 2);
			}
		}
Beispiel #21
0
		/// <summary>
		/// Creates a new LockToken and associates it with the supplied parent
		/// </summary>
		internal LockToken(Padlock parent)
		{
			Insist.IsNotNull(parent, "parent");

			_parent = parent;
		}