예제 #1
0
        public async Task DeduplicateBasicScenario()
        {
            var gate = TaskUtilities.CreateMutex();

            var winningLatch    = new SemaphoreSlim(0, 1);
            var losingLatch     = new SemaphoreSlim(0, 1);
            var completionLatch = new SemaphoreSlim(0, 1);

            var win  = winningTask();
            var lose = losingTask();
            await Task.WhenAll(win, lose);

            Contract.Assert(1 == await win);
            Contract.Assert(4 == await lose);

            async Task <int> winningTask()
            {
                await Task.Yield();

                await winningLatch.WaitAsync();

                return(await gate.DeduplicatedOperationAsync(async (w, c) =>
                {
                    losingLatch.Release();
                    await completionLatch.WaitAsync();
                    return 1;
                }, (w, c) =>
                {
                    Contract.Assert(false, "This should never happen");
                    return Task.FromResult(2);
                }));
            }

            async Task <int> losingTask()
            {
                await Task.Yield();

                winningLatch.Release();
                await losingLatch.WaitAsync();

                return(await gate.DeduplicatedOperationAsync((w, c) =>
                {
                    Contract.Assert(false, "This should never happen");
                    return Task.FromResult(3);
                }, (w, c) => {
                    completionLatch.Release();
                    return Task.FromResult(4);
                }));
            }
        }
예제 #2
0
        public async Task ResourceInvalidationRespectsReferenceCountBeforeShutdown()
        {
            var  stopLatch       = TaskUtilities.CreateMutex(taken: true);
            Task?outstandingTask = null;

            CounterCollection <ResourcePoolV2Counters>?counters = null;

            await RunTest <Key, Resource>(async (context, pool) =>
            {
                counters = pool.Counter;

                var key = new Key(0);
                await pool.UseAsync(context, key, async wrapper =>
                {
                    outstandingTask = pool.UseAsync(context, key, async wrapper2 =>
                    {
                        wrapper2.ReferenceCount.Should().Be(2);
                        stopLatch.Release();

                        try
                        {
                            await Task.Delay(Timeout.InfiniteTimeSpan, wrapper2.ShutdownToken);
                        }
                        catch (TaskCanceledException) { }

                        wrapper2.ReferenceCount.Should().Be(1);

                        counters[ResourcePoolV2Counters.CreatedResources].Value.Should().Be(1);
                        counters[ResourcePoolV2Counters.ReleasedResources].Value.Should().Be(0);
                        counters[ResourcePoolV2Counters.ShutdownAttempts].Value.Should().Be(0);

                        return(BoolResult.Success);
                    }).ShouldBeSuccess();

                    using var token = await stopLatch.AcquireAsync();
                    wrapper.Invalidate(context);

                    return(BoolResult.Success);
                }).ShouldBeSuccess();
            });

            Contract.AssertNotNull(counters);
            Contract.AssertNotNull(outstandingTask);

            // This should throw any exceptions that haven't been caught
            await outstandingTask;
        }
예제 #3
0
        public async Task ResourceInvalidationShutsDownOutstandingOperations()
        {
            var  stopLatch             = TaskUtilities.CreateMutex(taken: true);
            Task?witnessTask           = null;
            var  witnessedCancellation = false;

            await RunTest <Key, Resource>(async (context, pool) =>
            {
                var key = new Key(0);

                await pool.UseAsync(context, key, async wrapper =>
                {
                    await Task.Yield();

                    witnessTask = Task.Run(async() =>
                    {
                        // Ensuring it doesn't run on the UseAsync call
                        await Task.Yield();

                        // Allow the UseAsync call to invalidate
                        stopLatch.Release();

                        // Ensure we get cancelled
                        try
                        {
                            await Task.Delay(Timeout.InfiniteTimeSpan, wrapper.ShutdownToken);
                        }
                        catch (TaskCanceledException) { }

                        witnessedCancellation = true;
                    }).FireAndForgetErrorsAsync(context);

                    using var token = await stopLatch.AcquireAsync();
                    wrapper.Invalidate(context);
                    return(BoolResult.Success);
                }).ShouldBeSuccess();
            });

            Contract.AssertNotNull(witnessTask);
            await witnessTask;

            witnessedCancellation.Should().Be(true);
        }