public async Task IsolatedRequestsWaitForPrecedingReentrantsToClearOff()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            long callCount = 0;

            requests.PerformAndForget(async() => {
                Interlocked.Increment(ref callCount);
                await Task.Delay(100);
                Interlocked.Decrement(ref callCount);
            }, RequestMode.Reentrant);

            await Task.Delay(15);

            bool clashed = await requests.Perform(() => {
                var c = Interlocked.Read(ref callCount);
                return(Task.FromResult(c > 0));
            }, RequestMode.Isolated);

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(clashed, Is.False);
        }
        public async Task Closes_Immediately_WhenNoneWaiting()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool closed = false;

            requests.Close(() => {
                closed = true;
                return(Task.CompletedTask);
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(closed, Is.True);
        }
        public async Task WhenIdle_AwaitsCompletionOfDeactivation()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool closed = false;

            requests.Close(async() => {
                await Task.Delay(100);
                closed = true;
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(closed, Is.True);
        }
        public async Task Closing_Performed()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            bool closed = false;

            requests.PerformAndForget(() => Task.Delay(50));

            requests.Close(() => {
                closed = true;
                return(Task.CompletedTask);
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();

            Assert.That(closed, Is.True);
        }
        public async Task Closes_OnlyAfter_PreviouslyScheduledPerformances()
        {
            var exceptions = new ExceptionSink();
            var requests   = new RequestRunner(TaskScheduler.Default, exceptions);

            int calls = 0;

            Enumerable.Range(0, 100)
            .Select(_ => requests.Perform(async() => {
                Interlocked.Increment(ref calls);
                await Task.Delay(30);
                Interlocked.Decrement(ref calls);
            }))
            .ToArray();

            requests.Close(() => {
                Assert.That(calls, Is.EqualTo(0));
                return(Task.CompletedTask);
            });

            await requests.WhenIdle();

            exceptions.RethrowAll();
        }