示例#1
0
        public async Task Nested_Action()
        {
            // Verify that action reentrancy actually works.

            var inner1 = false;
            var inner2 = false;
            var inner3 = false;

            using (var mutex = new AsyncReentrantMutex())
            {
                await mutex.ExecuteActionAsync(
                    async() =>
                {
                    inner1 = true;

                    await mutex.ExecuteActionAsync(
                        async() =>
                    {
                        inner2 = true;

                        await mutex.ExecuteActionAsync(
                            async() =>
                        {
                            inner3 = true;

                            await Task.CompletedTask;
                        });
                    });
                });
            }

            Assert.True(inner1);
            Assert.True(inner2);
            Assert.True(inner3);
        }
示例#2
0
        public async Task Blocked_Func()
        {
            // Verify that non-nested function acquistions block.

            using (var mutex = new AsyncReentrantMutex())
            {
                var task1Time = DateTime.MinValue;
                var task2Time = DateTime.MinValue;

                var task1 = mutex.ExecuteFuncAsync(
                    async() =>
                {
                    task1Time = DateTime.UtcNow;

                    await Task.Delay(TimeSpan.FromSeconds(2));
                    return("TASK1");
                });

                var task2 = mutex.ExecuteFuncAsync(
                    async() =>
                {
                    task2Time = DateTime.UtcNow;

                    await Task.Delay(TimeSpan.FromSeconds(2));
                    return("TASK2");
                });

                var result1 = await task1;
                var result2 = await task2;

                Assert.Equal("TASK1", result1);
                Assert.Equal("TASK2", result2);

                // So the two tasks above could execute in any order, but only
                // one at a time.  With the delay, this means that the recorded
                // times should be at least 2 seconds apart.
                //
                // We'll verify at least a 1 second difference to mitigate any
                // clock skew.

                Assert.True(task1Time > DateTime.MinValue);
                Assert.True(task2Time > DateTime.MinValue);

                var delta = task1Time - task2Time;

                if (delta < TimeSpan.Zero)
                {
                    delta = -delta;
                }

                Assert.True(delta >= TimeSpan.FromSeconds(1));
            }
        }
示例#3
0
        public async Task Nested_Func()
        {
            // Verify that function reentrancy actually works.

            var inner1 = false;
            var inner2 = false;
            var inner3 = false;

            using (var mutex = new AsyncReentrantMutex())
            {
                var result = await mutex.ExecuteFuncAsync(
                    async() =>
                {
                    inner1 = true;

                    return(await mutex.ExecuteFuncAsync(
                               async() =>
                    {
                        inner2 = true;

                        return await mutex.ExecuteFuncAsync(
                            async() =>
                        {
                            inner3 = true;

                            return await Task.FromResult("HELLO WORLD!");
                        });
                    }));
                });

                Assert.Equal("HELLO WORLD!", result);
            }

            Assert.True(inner1);
            Assert.True(inner2);
            Assert.True(inner3);
        }
示例#4
0
        public async Task Dispose_Func()
        {
            // Verify that [ObjectDisposedException] is thrown for function tasks waiting
            // to acquire the mutex.

            var mutex = new AsyncReentrantMutex();

            try
            {
                // Hold the mutex for 2 seconds so the tasks below will block.

                var task1Acquired = false;
                var task2Acquired = false;
                var task3Acquired = false;

                var task1 = mutex.ExecuteFuncAsync(
                    async() =>
                {
                    task1Acquired = true;
                    await Task.Delay(TimeSpan.FromSeconds(2));
                    return("TASK1");
                });

                // Wait for [task1] to actually acquire to mutex.

                NeonHelper.WaitFor(() => task1Acquired, defaultTimeout);

                // Start two new tasks that will block.

                var task2 = mutex.ExecuteFuncAsync(
                    async() =>
                {
                    task2Acquired = true;
                    await Task.CompletedTask;
                    return("TASK2");
                });

                var task3 = mutex.ExecuteFuncAsync(
                    async() =>
                {
                    task3Acquired = true;
                    await Task.CompletedTask;
                    return("TASK1");
                });

                // Dispose the mutex.  We're expecting [task1] to complete normally and
                // [task2] and [task3] to fail with an [OperationCancelledException] with
                // their actions never being invoked.

                mutex.Dispose();

                await Assert.ThrowsAsync <ObjectDisposedException>(async() => await task2);

                Assert.False(task2Acquired);

                await Assert.ThrowsAsync <ObjectDisposedException>(async() => await task3);

                Assert.False(task3Acquired);

                await task1;
                Assert.True(task1Acquired);
            }
            finally
            {
                // Disposing this again shouldn't cause any trouble.

                mutex.Dispose();
            }
        }