예제 #1
0
        public void ShouldNotLeaveWaitersInQueueIfOperationIsCancelledAfterCallingRelease()
        {
            var @lock = new FifoSemaphore(1);

            @lock.Acquire(CancellationToken.None);

            try
            {
                var cts = new CancellationTokenSource();

                cts.Cancel();

                Assert.Throws <OperationCanceledException>(() => @lock.Acquire(cts.Token));

                Assert.Empty(@lock._waitQueue);

                cts = new CancellationTokenSource();

                @lock.ForTestingPurposesOnly().JustBeforeAddingToWaitQueue += () => cts.Cancel();

                Assert.Throws <OperationCanceledException>(() => @lock.Acquire(cts.Token));

                Assert.Equal(1, @lock._waitQueue.Count);

                Assert.True(@lock._waitQueue.First().IsCancelled);
            }
            finally
            {
                @lock.Release();
            }

            Assert.Empty(@lock._waitQueue);
        }
        /// <summary>
        /// Executes the specified action with thread safety.
        /// </summary>
        public void Execute(Action action)
        {
            GlobalFifoSemaphore.Acquire();

            try
            {
                action.Invoke();
            }

            finally
            {
                GlobalFifoSemaphore.Release();
            }
        }
예제 #3
0
        public void ShouldNotLeaveWaitersInQueueIfTimeoutAfterCallingRelease()
        {
            var @lock = new FifoSemaphore(1);

            @lock.Acquire(CancellationToken.None);

            try
            {
                Assert.False(@lock.TryAcquire(TimeSpan.Zero, CancellationToken.None));

                Assert.Equal(1, @lock._waitQueue.Count);

                Assert.True(@lock._waitQueue.First().IsTimedOut);
            }
            finally
            {
                @lock.Release();
            }

            Assert.Empty(@lock._waitQueue);
        }
        public void ShouldRespectSemaphoreLimit()
        {
            var allowed = 3;

            var inUse = 0;

            var @lock = new FifoSemaphore(allowed);

            var tasks = new List <Task>();

            int numberOfTasks = 20;

            int numberOfLocksPerTask = 10;

            bool tasksRunning = true;

            var verifyLimit = Task.Run(async() =>
            {
                while (tasksRunning)
                {
                    Assert.True(inUse <= allowed);

                    await Task.Delay(13);
                }
            });

            int totalNumberOfLocksTaken = 0;

            for (int i = 0; i < numberOfTasks; i++)
            {
                var task = Task.Run(() =>
                {
                    for (int j = 0; j < numberOfLocksPerTask; j++)
                    {
                        @lock.Acquire(CancellationToken.None);

                        Interlocked.Increment(ref inUse);

                        Interlocked.Increment(ref totalNumberOfLocksTaken);

                        try
                        {
                            Thread.Sleep(j);
                        }
                        finally
                        {
                            Interlocked.Decrement(ref inUse);

                            @lock.Release();
                        }
                    }
                });

                tasks.Add(task);
            }

            var waitResult = Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(30));

            Assert.True(waitResult);

            tasksRunning = false;

            waitResult = verifyLimit.Wait(TimeSpan.FromSeconds(30));

            Assert.True(waitResult);

            Assert.Equal(numberOfTasks * numberOfLocksPerTask, totalNumberOfLocksTaken);
        }