public void Creating_a_mutex_acquires_lock()
        {
            // Arrange
            var mutexName = "myname";

            // Act
            using (var mutex = new Mutex(mutexName))
            {
                // Assert
                mutex.Name.ShouldBe(mutexName);
                MutexManager.Mutexes.ContainsKey(mutexName).ShouldBeTrue();
                MutexManager.Mutexes[mutexName].State.ShouldBe(MutexState.Acquired);
                MutexManager.Mutexes[mutexName].Timestamp.ShouldBeGreaterThan(DateTime.MinValue);
                MutexManager.Mutexes[mutexName].ThreadId.ShouldBe(Thread.CurrentThread.ManagedThreadId);
            }

            // Assert
            MutexManager.Mutexes.ContainsKey(mutexName).ShouldBeFalse();
        }
        public void Competing_threads_block_on_same_mutex()
        {
            // Arrange
            var starts = new ConcurrentDictionary <string, DateTime>();
            var stops  = new ConcurrentDictionary <string, DateTime>();

            var mutexCreate = new Action <string, string, int>((id, mutexName, timeoutSeconds) =>
            {
                var ok = false;
                using (var mutex = new Mutex(mutexName))
                {
                    starts.GetOrAdd(id, DateTime.UtcNow);
                    Console.WriteLine("{0} started at {1}", id, starts[id]);

                    Thread.Sleep(TimeSpan.FromSeconds(timeoutSeconds));

                    stops.GetOrAdd(id, DateTime.UtcNow);
                    Console.WriteLine("{0} stopped at {1}", id, stops[id]);

                    ok = true;
                }

                ok.ShouldBeTrue();
            });

            var threadStart1 = new ThreadStart(() => mutexCreate("1", "Bob", 3));
            var threadStart2 = new ThreadStart(() => mutexCreate("2", "Bob", 2));
            var threadStart3 = new ThreadStart(() => mutexCreate("3", "Bob", 1));
            var threadStart4 = new ThreadStart(() => mutexCreate("4", "Jim", 2));

            // Act
            var thread1 = ThreadHelper.Start(threadStart1);
            var thread2 = ThreadHelper.Start(threadStart2);
            var thread3 = ThreadHelper.Start(threadStart3);
            var thread4 = ThreadHelper.Start(threadStart4);

            thread1.Join();
            thread2.Join();
            thread3.Join();
            thread4.Join();

            // Assert
            starts.Count.ShouldBe(4);
            stops.Count.ShouldBe(4);

            var keys = starts
                       .Where(s => s.Key != "4") // Bob only
                       .OrderBy(s => s.Value)
                       .Select(s => s.Key);

            var lastStop = DateTime.MinValue;

            foreach (var key in keys)
            {
                var start = starts[key];
                var stop  = stops[key];

                start.ShouldBeGreaterThanOrEqualTo(lastStop);
                stop.ShouldBeGreaterThan(start);

                lastStop = stop;
            }
        }