public void TestSingleDecreaseWork()
        {
            PartialThreadBlocker inst = new PartialThreadBlocker(4);
            Barrier startBar          = new Barrier(1 + 1);
            int     exitedCount       = 0;

            Task.Run(() =>
            {
                startBar.SignalAndWait();
                inst.Wait();
                Interlocked.Increment(ref exitedCount);
            });

            startBar.SignalAndWait();

            TimingAssert.AreEqual(5000, 4, () => inst.ExpectedWaiterCount);
            TimingAssert.AreEqual(5000, 1, () => inst.RealWaiterCount, "RealWaiterCount != 1");

            for (int i = 1; i <= 4; i++)
            {
                inst.SubstractExpectedWaiterCount(1);
                TimingAssert.AreEqual(5000, 4 - i, () => inst.ExpectedWaiterCount);
                TimingAssert.AreEqual(5000, i == 4 ? 0 : 1, () => inst.RealWaiterCount);
            }

            TimingAssert.AreEqual(5000, 1, () => Volatile.Read(ref exitedCount), "exitedCount != 1");
        }
        /// <summary>
        /// Активировать поток
        /// </summary>
        /// <returns>Успешность</returns>
        private bool ActivateThread()
        {
            if (EvaluatePausedThreadCountFromCombination(Volatile.Read(ref _dieSlotActiveFullThreadCountCombination)) == 0)
            {
                return(false);
            }

            bool wasThreadActivated = false;

            lock (_syncObject)
            {
                try { }
                finally
                {
                    if (IncrementActiveThreadCount())
                    {
                        _extThreadBlocker.SubstractExpectedWaiterCount(1);
                        //Console.WriteLine("Thread activated = " + ActiveThreadCount.ToString());
                        wasThreadActivated = true;
                    }
                }
            }
            return(wasThreadActivated);
        }
        public void TestFullCycle()
        {
            PartialThreadBlocker inst        = new PartialThreadBlocker(0);
            Barrier startBar                 = new Barrier(8 + 1);
            int     exitedCount              = 0;
            CancellationTokenSource tokenSrc = new CancellationTokenSource();

            Thread[] threads = new Thread[8];

            Func <int> sleepThCount = () =>
            {
                int result = 0;
                foreach (var th in threads)
                {
                    if ((th.ThreadState & ThreadState.WaitSleepJoin) != 0)
                    {
                        result++;
                    }
                }
                return(result);
            };

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(() =>
                {
                    startBar.SignalAndWait();
                    while (!tokenSrc.IsCancellationRequested)
                    {
                        inst.Wait();
                        SpinWaitHelper.SpinWait(1200);
                        Thread.Yield();
                    }
                    Interlocked.Increment(ref exitedCount);
                });

                threads[i].Start();
            }

            startBar.SignalAndWait();

            for (int i = 0; i < threads.Length; i++)
            {
                TimingAssert.AreEqual(5000, i, sleepThCount, "UP. Sleeping thread count != i");
                TimingAssert.AreEqual(5000, i, () => inst.RealWaiterCount, "UP. RealWaiterCount != i");
                TimingAssert.AreEqual(5000, i, () => inst.ExpectedWaiterCount, "UP. ExpectedWaiterCount != i");
                inst.AddExpectedWaiterCount(1);
                Thread.Sleep(10);
            }

            TimingAssert.AreEqual(5000, threads.Length, sleepThCount);
            TimingAssert.AreEqual(5000, threads.Length, () => inst.RealWaiterCount);
            TimingAssert.AreEqual(5000, threads.Length, () => inst.ExpectedWaiterCount);


            for (int i = threads.Length; i > 0; i--)
            {
                TimingAssert.AreEqual(5000, i, sleepThCount);
                TimingAssert.AreEqual(5000, i, () => inst.RealWaiterCount);
                TimingAssert.AreEqual(5000, i, () => inst.ExpectedWaiterCount);
                inst.SubstractExpectedWaiterCount(1);
                Thread.Sleep(10);
            }

            TimingAssert.AreEqual(5000, 0, sleepThCount, "Sleeping thread count != 0");
            TimingAssert.AreEqual(5000, 0, () => inst.RealWaiterCount, "RealWaiterCount != 0");
            TimingAssert.AreEqual(5000, 0, () => inst.ExpectedWaiterCount, "ExpectedWaiterCount != 0");


            tokenSrc.Cancel();

            TimingAssert.AreEqual(5000, threads.Length, () => Volatile.Read(ref exitedCount));
        }