private static async Task YieldableActionTask_Simple_Yield_Async()
        {
            var e = new ManualResetEvent(false);

            var task = new YieldableActionTask(token =>
            {
                Assert.IsFalse(token.IsYieldRequested);
                e.Set();

                while (!token.IsYieldRequested)
                {
                    ;
                }

                return(true);
            });

            task.RecalculatePriority();

            Assert.IsTrue(task.IsRunnable);
            Assert.AreEqual(1L, task.Priority);

            using var s = PhysicalScheduler.Create();
            using var l = new LogicalScheduler(s);

            l.Schedule(task);
            e.WaitOne();

            await l.PauseAsync();
        }
        private static async Task YieldableActionTask_Generic_Simple_Yield_Async()
        {
            var e = new ManualResetEvent(false);

            var x    = default(int);
            var task = new YieldableActionTask <int>((state, token) =>
            {
                Assert.IsFalse(token.IsYieldRequested);
                x = state;
                e.Set();

                while (!token.IsYieldRequested)
                {
                    ;
                }

                return(true);
            }, 42);

            task.RecalculatePriority();

            Assert.IsTrue(task.IsRunnable);
            Assert.AreEqual(1L, task.Priority);

            using (var s = PhysicalScheduler.Create())
                using (var l = new LogicalScheduler(s))
                {
                    l.Schedule(task);
                    e.WaitOne();

                    await l.PauseAsync();
                }

            Assert.AreEqual(42, x);
        }
        private static async Task YieldableActionTask_Simple_YieldAndResume_Async()
        {
            var e1 = new AutoResetEvent(false);
            var e2 = new AutoResetEvent(false);
            var p1 = new ManualResetEvent(false);

            var state = 0;

            var task = new YieldableActionTask(token =>
            {
                Assert.IsFalse(token.IsYieldRequested);

                switch (state)
                {
                case 0:
                    e1.Set();

                    while (!token.IsYieldRequested)
                    {
                        ;
                    }

                    p1.Set();

                    state++;
                    return(false);

                case 1:
                    e2.Set();
                    state++;
                    return(true);

                default:
                    Assert.Fail();
                    break;
                }

                return(true);
            });

            task.RecalculatePriority();

            Assert.IsTrue(task.IsRunnable);
            Assert.AreEqual(1L, task.Priority);

            using var s = PhysicalScheduler.Create();
            using var l = new LogicalScheduler(s);

            l.Schedule(task);
            e1.WaitOne();

            await l.PauseAsync();

            p1.WaitOne();

            l.Continue();
            e2.WaitOne();
        }
        public void YieldableActionTask_Simple()
        {
            var e    = new ManualResetEvent(false);
            var task = new YieldableActionTask(token => e.Set());

            task.RecalculatePriority();

            Assert.IsTrue(task.IsRunnable);
            Assert.AreEqual(1L, task.Priority);

            using var s = PhysicalScheduler.Create();
            using var l = new LogicalScheduler(s);

            l.Schedule(task);
            e.WaitOne();
        }
        public void YieldableActionTask_Generic_Simple()
        {
            var e    = new ManualResetEvent(false);
            var x    = default(int);
            var task = new YieldableActionTask <int>((state, token) => { x = state; e.Set(); return(true); }, 42);

            task.RecalculatePriority();

            Assert.IsTrue(task.IsRunnable);
            Assert.AreEqual(1L, task.Priority);

            using (var s = PhysicalScheduler.Create())
                using (var l = new LogicalScheduler(s))
                {
                    l.Schedule(task);
                    e.WaitOne();
                }

            Assert.AreEqual(42, x);
        }
        private static async Task YieldableActionTask_Generic_YieldAndResume_Async()
        {
            const int N = 10;

            var isRunning      = new AutoResetEvent(false);
            var stoppedRunning = new AutoResetEvent(false);
            var iterationCount = new CountdownEvent(N);

            var i      = 2;
            var primes = new List <int>();

            var task = new YieldableActionTask <List <int> >((primes2, token) =>
            {
                Assert.AreSame(primes, primes2);

                isRunning.Set();

                var sw = Stopwatch.StartNew();

                while (true)
                {
                    if (sw.ElapsedMilliseconds > 50 && token.IsYieldRequested)
                    {
                        break;
                    }

                    var isPrime = true;

                    for (var d = 2; d <= Math.Sqrt(i); d++)
                    {
                        if (i % d == 0)
                        {
                            isPrime = false;
                            break;
                        }
                    }

                    if (isPrime)
                    {
                        primes2.Add(i);
                    }

                    i++;
                }

                iterationCount.Signal();

                try
                {
                    if (iterationCount.CurrentCount == 0)
                    {
                        return(true);
                    }

                    return(false);
                }
                finally
                {
                    stoppedRunning.Set();
                }
            }, primes);

            task.RecalculatePriority();

            Assert.IsTrue(task.IsRunnable);
            Assert.AreEqual(1L, task.Priority);

            using (var s = PhysicalScheduler.Create())
                using (var l = new LogicalScheduler(s))
                {
                    l.Schedule(task);

                    for (var j = 0; j < N; j++)
                    {
                        isRunning.WaitOne();
                        await l.PauseAsync();

                        stoppedRunning.WaitOne();
                        l.Continue();
                    }

                    iterationCount.Wait();
                }

            Assert.IsTrue(Primes().Take(primes.Count).SequenceEqual(primes));
        }