private void RunComplexTest(StaticPoolManager <int> testInst, int threadCount, int opCount, int pauseSpin, bool autoAddRemove)
        {
            Thread[] threads  = new Thread[threadCount];
            Barrier  startBar = new Barrier(threadCount + 1);

            int opCountPerThread = opCount / threadCount;

            Action thAct = () =>
            {
                Random localRand = new Random(Thread.CurrentThread.ManagedThreadId + Environment.TickCount);
                int    pasueDiff = (int)Math.Ceiling(pauseSpin / 4.0);

                startBar.SignalAndWait();

                int execOp = 0;
                while (execOp++ < opCountPerThread)
                {
                    if (autoAddRemove && (testInst.ElementCount == 0 || localRand.Next(5) == 0))
                    {
                        testInst.AddElement(execOp);
                    }

                    using (var el = testInst.Rent())
                    {
                        if (autoAddRemove && testInst.ElementCount > 1 && localRand.Next(5) == 0)
                        {
                            testInst.RemoveElement(el);
                        }

                        int spinCount = localRand.Next(pauseSpin - pasueDiff, pauseSpin + pasueDiff);
                        SpinWaitHelper.SpinWait(spinCount);
                    }
                }

                if (autoAddRemove)
                {
                    testInst.AddElement(execOp);
                }
            };


            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ThreadStart(thAct));
            }

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Start();
            }

            startBar.SignalAndWait();

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Join();
            }

            Assert.AreEqual(testInst.ElementCount, testInst.FreeElementCount);
        }
示例#2
0
 public void SpinWaitOnNetCore31IsAlwaysNormalized()
 {
     for (int i = 0; i < 10; i++)
     {
         int normValue = SpinWaitHelper.GetSpinWaitNormalizationCoef();
         Assert.AreEqual(1, normValue);
         Thread.Sleep(1);
     }
 }
示例#3
0
        public void SpinWaitPerformNormalizationInBackground()
        {
            while (!SpinWaitHelper.NormalizationCoefCalculated)
            {
                SpinWaitHelper.SpinWait(100);
            }

            this.TestContext.WriteLine($"Normalization coef: {SpinWaitHelper.NormalizationCoef}");
        }
        public void TestExecuteAndForget()
        {
            var command   = new MockCommand(true);
            var processor = new MockCommandProcessor();

            processor.Init(Assert.IsNull);
            processor.ExecuteAndForget(1, command);
            Assert.IsTrue(SpinWaitHelper.SpinWaitForCondition(() => command.CurrentState == false, 500));
            //new state should be false
        }
示例#5
0
        public void SpinningNormalizedValidation()
        {
            while (!SpinWaitHelper.NormalizationCoefCalculated)
            {
                SpinWaitHelper.SpinWait(100);
            }

            SpinningNormalizedValidationCore();
            SpinningNormalizedValidationCore();
            SpinningNormalizedValidationCore();
        }
示例#6
0
        private static TimeSpan TestObjectPoolWithSyncPrior(PrioritizedElementsContainer <PoolElem> pool, int threadCount, int opCount, int pauseSpin)
        {
            Thread[] threads  = new Thread[threadCount];
            Barrier  startBar = new Barrier(threadCount + 1);

            int opCountPerThread = opCount / threadCount;

            Action thAct = () =>
            {
                startBar.SignalAndWait();

                int execOp = 0;
                while (execOp++ < opCountPerThread)
                {
                    PoolElementWrapper <PoolElem> el = null;
                    try
                    {
                        el = pool.Take();
                        //Thread.Sleep(pauseSpin);
                        SpinWaitHelper.SpinWait(pauseSpin);
                    }
                    finally
                    {
                        pool.Release(el);
                    }
                }
            };


            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ThreadStart(thAct));
            }

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Start();
            }

            startBar.SignalAndWait();
            Stopwatch sw = Stopwatch.StartNew();

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Join();
            }

            sw.Stop();

            Console.WriteLine("PrioritizedElementsContainer. Elapsed = " + sw.ElapsedMilliseconds.ToString() + "ms");

            return(sw.Elapsed);
        }
示例#7
0
        private void SpinningNormalizedValidationCore()
        {
            var sw = Stopwatch.StartNew();

            for (int i = 0; i < 500; i++)
            {
                SpinWaitHelper.SpinWait(1000 * 1000 / 37);
            }
            sw.Stop();
            TestContext.WriteLine($"Measured time: {sw.ElapsedMilliseconds}ms");
            // Expect 500ms (can be large due to context switch)
            //Assert.IsTrue(sw.ElapsedMilliseconds > 400 && sw.ElapsedMilliseconds < 600, "Measured time: " + sw.ElapsedMilliseconds.ToString());
        }
示例#8
0
        private void RunComplexTest(TestDynamicPool testInst, int threadCount, int opCount, int pauseSpin, bool faultElements)
        {
            Thread[] threads  = new Thread[threadCount];
            Barrier  startBar = new Barrier(threadCount + 1);

            int opCountPerThread = opCount / threadCount;

            Action thAct = () =>
            {
                Random localRand = new Random(Thread.CurrentThread.ManagedThreadId + Environment.TickCount);
                int    pasueDiff = (int)Math.Ceiling(pauseSpin / 4.0);

                startBar.SignalAndWait();

                int execOp = 0;
                while (execOp++ < opCountPerThread)
                {
                    using (var el = testInst.Rent())
                    {
                        if (faultElements && localRand.Next(10) == 0)
                        {
                            el.Element.MakeInvalid();
                        }

                        int spinCount = localRand.Next(pauseSpin - pasueDiff, pauseSpin + pasueDiff);
                        SpinWaitHelper.SpinWait(spinCount);
                    }
                }
            };


            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ThreadStart(thAct));
            }

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Start();
            }

            startBar.SignalAndWait();

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Join();
            }

            Assert.AreEqual(testInst.ElementCount, testInst.FreeElementCount);
        }
 public void TestRun_With_Exception_OnCompleted()
 {
     using (var target = new ConsumerWorker <int, int>())
     {
         Exception newEx = null;
         target.Init((k, i) => { }, ex => newEx = ex);
         var q = new MockQueue {
             1
         };
         target.Run(q, w => { throw new ApplicationException("Test Exception"); });
         Assert.IsTrue(SpinWaitHelper.SpinWaitForCondition(() => newEx != null, 1000));
         Assert.IsInstanceOfType(newEx, typeof(ApplicationException));
     }
 }
示例#10
0
        private static TimeSpan TestNewPool(Qoollo.Turbo.ObjectPools.ObjectPoolManager <PoolElem> pool, int threadCount, int opCount, int pauseSpin)
        {
            Thread[] threads  = new Thread[threadCount];
            Barrier  startBar = new Barrier(threadCount + 1);

            int opCountPerThread = opCount / threadCount;

            Action thAct = () =>
            {
                startBar.SignalAndWait();

                int execOp = 0;
                while (execOp++ < opCountPerThread)
                {
                    using (var el = pool.Rent())
                    {
                        //Thread.Sleep(pauseSpin);
                        SpinWaitHelper.SpinWait(pauseSpin);
                    }
                }
            };


            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ThreadStart(thAct));
            }

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Start();
            }

            startBar.SignalAndWait();
            Stopwatch sw = Stopwatch.StartNew();

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Join();
            }

            sw.Stop();

            Console.WriteLine(pool.ToString() + ". Elapsed = " + sw.ElapsedMilliseconds.ToString() + "ms");

            return(sw.Elapsed);
        }
示例#11
0
        public void AddTakeMultithreadTest()
        {
            const int ItemsCount = 10000;

            using (var queue = new BlockingQueue <int>())
                using (var barrier = new Barrier(2))
                {
                    ConcurrentBag <int> bag = new ConcurrentBag <int>();

                    var task1 = Task.Run(() =>
                    {
                        barrier.SignalAndWait();
                        Parallel.For(0, ItemsCount, val =>
                        {
                            queue.Add(val);
                            SpinWaitHelper.SpinWait(val % 16);
                        });
                    });

                    var task2 = Task.Run(() =>
                    {
                        barrier.SignalAndWait();
                        Parallel.For(0, 10000, val =>
                        {
                            int res = 0;
                            if (!queue.TryTake(out res, 10000))
                            {
                                Assert.Fail("Value was expected in MemoryQueue");
                            }
                            bag.Add(res);
                            SpinWaitHelper.SpinWait((val + 5) % 16);
                        });
                    });

                    Task.WaitAll(task1, task2);

                    Assert.AreEqual(0, queue.Count);
                    Assert.AreEqual(ItemsCount, bag.Count);

                    var array = bag.ToArray();
                    Array.Sort(array);
                    for (int i = 0; i < array.Length; i++)
                    {
                        Assert.AreEqual(i, array[i], "i != array[i]");
                    }
                }
        }
示例#12
0
        // =========================

        private void AddWakesUpTest(LevelingQueue <int> queue)
        {
            while (queue.TryAdd(100))
            {
                ;                       // Fill queue
            }
            if (queue.IsBackgroundTransferingEnabled)
            {
                SpinWait sw = new SpinWait();
                while (queue.IsBackgroundInWork && sw.Count < 100)
                {
                    sw.SpinOnce();
                }

                for (int i = 0; i < 100; i++)
                {
                    queue.TryAdd(100);
                    SpinWaitHelper.SpinWait(12);
                }
            }

            Barrier bar       = new Barrier(2);
            int     addResult = 0;
            Task    task      = Task.Run(() =>
            {
                bar.SignalAndWait();
                AtomicSet(ref addResult, queue.TryAdd(-100, 60000));
            });

            bar.SignalAndWait();
            Thread.Sleep(10);
            Assert.AreEqual(0, Volatile.Read(ref addResult));

            queue.Take();
            if (queue.AddingMode == LevelingQueueAddingMode.PreserveOrder && !queue.IsBackgroundTransferingEnabled)
            {
                int item;
                while (queue.TryTake(out item))
                {
                    ;
                }
            }

            TimingAssert.AreEqual(10000, 1, () => Volatile.Read(ref addResult));

            task.Wait();
        }
示例#13
0
        public void SpinWaitSmallFluctuation()
        {
            List <int> measureResults = new List <int>();

            for (int i = 0; i < 10; i++)
            {
                measureResults.Add(SpinWaitHelper.GetSpinWaitNormalizationCoef());
                Thread.Sleep(100);
            }

            int minMeasure = measureResults.Min();
            int maxMeasure = measureResults.Max();

            TestContext.WriteLine($"MinMeasure: {minMeasure}, MaxMeasure: {maxMeasure}");
            // Fluctuation can actually be high in some scenarious
            //Assert.IsTrue(maxMeasure - minMeasure <= 1);
        }
示例#14
0
        public void AddTakeSequentialTest()
        {
            const int ItemsCount = 10000;

            using (var queue = new BlockingQueue <int>())
                using (var barrier = new Barrier(2))
                {
                    List <int> bag = new List <int>();

                    var task1 = Task.Run(() =>
                    {
                        barrier.SignalAndWait();
                        for (int val = 0; val < ItemsCount; val++)
                        {
                            queue.Add(val);
                            SpinWaitHelper.SpinWait(val % 16);
                        }
                    });

                    var task2 = Task.Run(() =>
                    {
                        barrier.SignalAndWait();
                        for (int val = 0; val < ItemsCount; val++)
                        {
                            int res = 0;
                            if (!queue.TryTake(out res, 10000))
                            {
                                Assert.Fail("Value was expected in MemoryQueue");
                            }
                            bag.Add(res);
                            SpinWaitHelper.SpinWait((val + 5) % 16);
                        }
                    });

                    Task.WaitAll(task1, task2);

                    Assert.AreEqual(0, queue.Count);
                    Assert.AreEqual(ItemsCount, bag.Count);

                    for (int i = 0; i < bag.Count; i++)
                    {
                        Assert.AreEqual(i, bag[i], "i != bag[i]");
                    }
                }
        }
        private static TimeSpan MeasureCountingProc(int count, int thCount, int spin)
        {
            int                value    = 0;
            Barrier            barStart = new Barrier(thCount + 1);
            Barrier            barEnd   = new Barrier(thCount + 1);
            EntryCountingEvent inst     = new EntryCountingEvent();

            Action act = () =>
            {
                barStart.SignalAndWait();

                while (Interlocked.Increment(ref value) < count)
                {
                    using (var guard = inst.TryEnter())
                    {
                        SpinWaitHelper.SpinWait(spin);
                    }
                }

                barEnd.SignalAndWait();
            };

            Thread[] threads = new Thread[thCount];

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i] = new Thread(new ThreadStart(act));
                threads[i].Start();
            }

            barStart.SignalAndWait();
            Stopwatch sw = Stopwatch.StartNew();

            barEnd.SignalAndWait();
            sw.Stop();

            for (int i = 0; i < threads.Length; i++)
            {
                threads[i].Join();
            }
            inst.Dispose();

            Console.WriteLine($"Counting. Elapsed = {sw.ElapsedMilliseconds}ms");
            return(sw.Elapsed);
        }
        // ===================


        private void RunWriteAbort(PersistentDiskQueueSegment <int> segment, int count, Random rnd)
        {
            Barrier     bar        = new Barrier(2);
            Exception   observedEx = null;
            int         added      = 0;
            ThreadStart act        = () =>
            {
                bar.SignalAndWait();
                int item = 1;
                try
                {
                    while (segment.TryAdd(item++))
                    {
                        Interlocked.Increment(ref added);
                    }
                }
                catch (Exception ex)
                {
                    if (!(ex is ThreadAbortException))
                    {
                        Volatile.Write(ref observedEx, ex);
                    }
                }
                Interlocked.Add(ref added, count);
            };

            Thread th = new Thread(act);

            th.Start();
            bar.SignalAndWait();

            while (Volatile.Read(ref added) < count)
            {
                SpinWaitHelper.SpinWait(20);
            }

            SpinWaitHelper.SpinWait(rnd.Next(4000));
            th.Abort();
            th.Join();

            if (observedEx != null)
            {
                throw observedEx;
            }
        }
示例#17
0
        public void TryAcceptWorkerMock()
        {
            var worker       = new MockWorker();
            var completed    = new ManualResetEventSlim(false);
            var dequeueCount = new CountdownEvent(1);
            var target       = new ConsumerQueue <int, int>(11, w =>
            {
                Assert.AreSame(worker, w);
                completed.Set();
            }, q => dequeueCount.Signal()); //test that correct instance passed

            target.Add(1);
            Task task = Task.Factory.StartNew(() => target.TryAcceptWorker(worker));

            Assert.IsTrue(SpinWaitHelper.SpinWaitForCondition(() => target.IsBusy, 1000));
            //should become busy when accept occurs
            task.Wait();
            Assert.IsTrue(dequeueCount.Wait(1000)); //completed should be called
            Assert.IsTrue(completed.Wait(1000));    //completed should be called
        }
示例#18
0
        /// <summary>
        /// Perform a spin
        /// </summary>
        public void SpinOnce()
        {
            if (this.NextSpinWillYield)
            {
                int yieldThreshold = _yieldThreshold;
                if (yieldThreshold == 0)
                {
                    yieldThreshold = DefaultYieldThreshold;
                }

                int num = (_count >= yieldThreshold) ? (_count - yieldThreshold) : _count;

                if (num % SLEEP_1_EVERY_HOW_MANY_TIMES == (SLEEP_1_EVERY_HOW_MANY_TIMES - 1))
                {
                    Thread.Sleep(1);
                }
                else
                {
                    if (num % SLEEP_0_EVERY_HOW_MANY_TIMES == (SLEEP_0_EVERY_HOW_MANY_TIMES - 1))
                    {
                        Thread.Sleep(0);
                    }
                    else
                    {
                        Thread.Yield();
                    }
                }
            }
            else
            {
                int spinCount = _singleSpinCount;
                if (spinCount == 0)
                {
                    spinCount = DefaultSingleSpinCount;
                }

                SpinWaitHelper.SpinWait(spinCount * _count + spinCount);
            }
            this._count = ((this._count == int.MaxValue) ? 10 : (this._count + 1));
        }
示例#19
0
        private void Create_Add_AndWaitForCompletion(bool suspendWorkers)
        {
            const int itemsTotal = 20;
            const int consumersTotal = 20;
            using (var countdownConsumer = new CountdownEvent(itemsTotal))
            using (var countdownAdd = new CountdownEvent(itemsTotal))
            {
                using (var target = new MockTaskPool(() => (k, i) =>
                {
                    Assert.AreEqual(k, i);
                    countdownConsumer.Signal();
                },
                    (k, i) =>
                    {
                        Assert.AreEqual(k, i);
                        countdownAdd.Signal();
                    },
                    Assert.IsNull, consumersTotal, suspendWorkers, false, 1000))
                {
                    Assert.AreEqual(consumersTotal, target.PoolSize);

                    Task.Factory.StartNew(() =>
                    {
                        for (int i = 0; i < itemsTotal; i++)
                        {
                            target.Add(i, i);
                        }
                    });
                    Assert.IsTrue(SpinWaitHelper.SpinWaitForCondition(() => target.PendingRequests > 0, 1000));
                    Assert.IsTrue(countdownAdd.Wait(5000)); //should invoke add callback within timeout
                    Assert.IsTrue(countdownConsumer.Wait(5000)); //should invoke consumer within timeout

                    Assert.IsTrue(SpinWaitHelper.SpinWaitForCondition(() => target.IndexSize == itemsTotal, 1000));

                    Assert.IsTrue(SpinWaitHelper.SpinWaitForCondition(() => target.PoolSize == consumersTotal, 10000));

                    Assert.AreEqual(0, target.PendingRequests);
                }
            }
        }
示例#20
0
 /// <summary>
 /// Custom spinning logic implementation. Tweaked for SemaphoreLight (roughly equivalent to .NET Core 3.0 SpinWait logic, better than .NET Framework SpinWait logic)
 /// </summary>
 /// <param name="spinNumber">Number of the spin</param>
 private static void SpinOnce(int spinNumber)
 {
     if (spinNumber < SPIN_YIELD_THRESHOLD)
     {
         SpinWaitHelper.SpinWait(8 + 2 * spinNumber);
     }
     else
     {
         if ((spinNumber - SPIN_YIELD_THRESHOLD) % SPIN_SLEEP0_PERIOD == (SPIN_SLEEP0_PERIOD - 1))
         {
             Thread.Sleep(0);
         }
         else if ((spinNumber - SPIN_YIELD_THRESHOLD) % 2 == 1 && _processorCount > 1)
         {
             SpinWaitHelper.SpinWait(8);
         }
         else
         {
             Thread.Yield();
         }
     }
 }
示例#21
0
        // ==========================


        private void PreserveOrderTest(LevelingQueue <int> queue, int elemCount)
        {
            Barrier bar = new Barrier(2);
            CancellationTokenSource cancelled = new CancellationTokenSource();
            List <int> takenElems             = new List <int>(elemCount + 1);

            Action addAction = () =>
            {
                int    curElem = 0;
                Random rnd     = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId);

                bar.SignalAndWait();
                while (curElem < elemCount)
                {
                    if (rnd.Next(100) == 0)
                    {
                        queue.AddForced(curElem);
                    }
                    else
                    {
                        queue.Add(curElem);
                    }

                    if (rnd.Next(100) == 0)
                    {
                        Thread.Yield();
                    }
                    SpinWaitHelper.SpinWait(rnd.Next(12));

                    curElem++;
                }

                cancelled.Cancel();
            };

            StringBuilder badInfo = new StringBuilder();

            Action takeAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId);

                bar.SignalAndWait();
                try
                {
                    while (!cancelled.IsCancellationRequested)
                    {
                        takenElems.Add(queue.Take(cancelled.Token));
                        //if (takenElems[takenElems.Count - 1] != takenElems.Count - 1)
                        //    badInfo.Append("Is taken from high = " + queue.LastTakeTop.ToString());

                        if (rnd.Next(100) == 0)
                        {
                            Thread.Yield();
                        }
                        SpinWaitHelper.SpinWait(rnd.Next(12));
                    }
                }
                catch (OperationCanceledException) { }

                int item = 0;
                while (queue.TryTake(out item))
                {
                    takenElems.Add(item);
                }
            };


            var sw = System.Diagnostics.Stopwatch.StartNew();

            Task addTask  = Task.Factory.StartNew(addAction, TaskCreationOptions.LongRunning);
            Task takeTask = Task.Factory.StartNew(takeAction, TaskCreationOptions.LongRunning);

            Task.WaitAll(addTask, takeTask);

            Assert.AreEqual(elemCount, takenElems.Count);
            for (int i = 0; i < takenElems.Count; i++)
            {
                if (i != takenElems[i])
                {
                    Assert.AreEqual(i, takenElems[i], $"i != takenElems[i], nextItem = {takenElems[i + 1]}, badInfo = '{badInfo}'");
                }
            }
        }
示例#22
0
        private static TimeSpan RunConcurrentMon(string name, int elemCount, int addThCount, int takeThCount, int addSpin, int takeSpin)
        {
            MonitorThreadSafeQueue <int> col = new MonitorThreadSafeQueue <int>(10000);

            CancellationTokenSource srcCancel = new CancellationTokenSource();

            Thread[] addThreads  = new Thread[addThCount];
            Thread[] takeThreads = new Thread[takeThCount];

            int        addedElemCount = 0;
            List <int> globalList     = new List <int>();

            Barrier barierStart  = new Barrier(1 + addThreads.Length + takeThreads.Length);
            Barrier barierAdders = new Barrier(1 + addThreads.Length);
            Barrier barierTakers = new Barrier(1 + takeThreads.Length);

            Action addAction = () =>
            {
                barierStart.SignalAndWait();

                int index = 0;
                while ((index = Interlocked.Increment(ref addedElemCount)) <= elemCount)
                {
                    col.Add(index - 1);
                    SpinWaitHelper.SpinWait(addSpin);
                }

                barierAdders.SignalAndWait();
            };


            Action takeAction = () =>
            {
                CancellationToken myToken = srcCancel.Token;
                List <int>        valList = new List <int>(elemCount / takeThCount + 100);

                barierStart.SignalAndWait();

                try
                {
                    while (!srcCancel.IsCancellationRequested)
                    {
                        int val = 0;
                        val = col.Take(myToken);

                        valList.Add(val);
                        SpinWaitHelper.SpinWait(takeSpin);
                    }
                }
                catch (OperationCanceledException)
                {
                }

                int val2 = 0;
                while (col.TryTake(out val2))
                {
                    valList.Add(val2);
                }

                barierTakers.SignalAndWait();

                lock (globalList)
                {
                    globalList.AddRange(valList);
                }
            };

            for (int i = 0; i < addThreads.Length; i++)
            {
                addThreads[i] = new Thread(new ThreadStart(addAction));
            }
            for (int i = 0; i < takeThreads.Length; i++)
            {
                takeThreads[i] = new Thread(new ThreadStart(takeAction));
            }


            for (int i = 0; i < takeThreads.Length; i++)
            {
                takeThreads[i].Start();
            }
            for (int i = 0; i < addThreads.Length; i++)
            {
                addThreads[i].Start();
            }

            barierStart.SignalAndWait();

            Stopwatch sw = Stopwatch.StartNew();

            barierAdders.SignalAndWait();
            srcCancel.Cancel();
            barierTakers.SignalAndWait();
            sw.Stop();

            for (int i = 0; i < addThreads.Length; i++)
            {
                addThreads[i].Join();
            }
            for (int i = 0; i < takeThreads.Length; i++)
            {
                takeThreads[i].Join();
            }

            globalList.Sort();
            if (globalList.Count != elemCount)
            {
                Console.WriteLine("Bad count");
            }

            for (int i = 0; i < globalList.Count; i++)
            {
                if (globalList[i] != i)
                {
                    Console.WriteLine("invalid elements");
                    break;
                }
            }

            if (name != null)
            {
                Console.WriteLine(name + ". MonQ. Time = " + sw.ElapsedMilliseconds.ToString() + "ms");
            }
            return(sw.Elapsed);
        }
        // ===================

        private void PreserveOrderTest(PersistentDiskQueueSegment <int> segment, int elemCount)
        {
            Assert.IsTrue(elemCount <= segment.Capacity);

            Barrier bar = new Barrier(2);
            CancellationTokenSource cancelled = new CancellationTokenSource();
            List <int> takenElems             = new List <int>(elemCount + 1);

            Action addAction = () =>
            {
                int    curElem = 0;
                Random rnd     = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId);

                bar.SignalAndWait();
                while (curElem < elemCount)
                {
                    if (rnd.Next(100) == 0)
                    {
                        segment.AddForced(curElem);
                    }
                    else
                    {
                        Assert.IsTrue(segment.TryAdd(curElem));
                    }

                    if (rnd.Next(100) == 0)
                    {
                        Thread.Yield();
                    }
                    SpinWaitHelper.SpinWait(rnd.Next(12));

                    curElem++;
                }

                cancelled.Cancel();
            };

            Action takeAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId);

                bar.SignalAndWait();
                try
                {
                    while (!cancelled.IsCancellationRequested)
                    {
                        int curItem = 0;
                        if (segment.TryTake(out curItem))
                        {
                            takenElems.Add(curItem);
                        }
                        if (rnd.Next(100) == 0)
                        {
                            Thread.Yield();
                        }
                        SpinWaitHelper.SpinWait(rnd.Next(12));
                    }
                }
                catch (OperationCanceledException) { }

                int item = 0;
                while (segment.TryTake(out item))
                {
                    takenElems.Add(item);
                }
            };


            var sw = System.Diagnostics.Stopwatch.StartNew();

            Task addTask  = Task.Factory.StartNew(addAction, TaskCreationOptions.LongRunning);
            Task takeTask = Task.Factory.StartNew(takeAction, TaskCreationOptions.LongRunning);

            Task.WaitAll(addTask, takeTask);

            Assert.AreEqual(elemCount, takenElems.Count);
            for (int i = 0; i < takenElems.Count; i++)
            {
                if (i != takenElems[i])
                {
                    Assert.AreEqual(i, takenElems[i], $"i != takenElems[i], nextItem = {takenElems[i + 1]}");
                }
            }
        }
示例#24
0
 public void ProcessorDetectionIsNotFail()
 {
     TestContext.WriteLine(SpinWaitHelper.GetProcessorKind().ToString());
 }
示例#25
0
 public void FrameworkNotSupportSpinWaitNormalization()
 {
     Assert.IsFalse(SpinWaitHelper.IsFrameworkSupportSpinWaitNormalization());
 }
        // =========================

        private void RunComplexTest(PersistentDiskQueueSegment <int> segment, int elemCount, int thCount)
        {
            Assert.IsTrue(elemCount <= segment.Capacity);

            int atomicRandom = 0;

            int trackElemCount = elemCount;
            int addFinished    = 0;

            Thread[] threadsTake = new Thread[thCount];
            Thread[] threadsAdd  = new Thread[thCount];

            CancellationTokenSource tokSrc = new CancellationTokenSource();

            List <int> global = new List <int>(elemCount);

            Action addAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2);

                while (true)
                {
                    int item = Interlocked.Decrement(ref trackElemCount);
                    if (item < 0)
                    {
                        break;
                    }

                    if (rnd.Next(100) == 0)
                    {
                        segment.AddForced(item);
                    }
                    else
                    {
                        Assert.IsTrue(segment.TryAdd(item));
                    }


                    int sleepTime = rnd.Next(12);

                    int tmpItem = 0;
                    if (segment.TryPeek(out tmpItem) && tmpItem == item)
                    {
                        sleepTime += 12;
                    }

                    if (sleepTime > 0)
                    {
                        SpinWaitHelper.SpinWait(sleepTime);
                    }
                }

                Interlocked.Increment(ref addFinished);
            };


            Action takeAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2);

                List <int> data = new List <int>();

                try
                {
                    while (Volatile.Read(ref addFinished) < thCount)
                    {
                        int tmp = 0;
                        if (segment.TryTake(out tmp))
                        {
                            data.Add((int)tmp);
                        }

                        int sleepTime = rnd.Next(12);
                        if (sleepTime > 0)
                        {
                            SpinWaitHelper.SpinWait(sleepTime);
                        }
                    }
                }
                catch (OperationCanceledException) { }

                int tmp2;
                while (segment.TryTake(out tmp2))
                {
                    data.Add((int)tmp2);
                }

                lock (global)
                    global.AddRange(data);
            };


            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i] = new Thread(new ThreadStart(takeAction));
            }
            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i] = new Thread(new ThreadStart(addAction));
            }


            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i].Start();
            }
            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i].Start();
            }


            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i].Join();
            }
            tokSrc.Cancel();
            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i].Join();
            }


            Assert.AreEqual(elemCount, global.Count);
            global.Sort();

            for (int i = 0; i < elemCount; i++)
            {
                Assert.AreEqual(i, global[i]);
            }
        }
示例#27
0
        private void RunComplexTest(ConcurrentBatchingQueue <int> q, int elemCount, int thCount)
        {
            int atomicRandom = 0;

            int trackElemCount = elemCount;
            int addFinished    = 0;

            Thread[] threadsTake     = new Thread[thCount];
            Thread[] threadsAdd      = new Thread[thCount];
            Thread   enumerateThread = null;

            CancellationTokenSource tokSrc = new CancellationTokenSource();

            List <int> global = new List <int>(elemCount);

            Action addAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2);

                while (true)
                {
                    int item = Interlocked.Decrement(ref trackElemCount);
                    if (item < 0)
                    {
                        break;
                    }

                    q.Enqueue(item);

                    int sleepTime = rnd.Next(12);
                    if (sleepTime > 0)
                    {
                        SpinWaitHelper.SpinWait(sleepTime);
                    }
                }

                Interlocked.Increment(ref addFinished);
            };


            Action takeAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2);

                List <int> data = new List <int>();

                try
                {
                    while (Volatile.Read(ref addFinished) < thCount)
                    {
                        int[] tmp;
                        if (q.TryDequeue(out tmp))
                        {
                            data.AddRange(tmp);
                        }

                        int sleepTime = rnd.Next(12);
                        if (sleepTime > 0)
                        {
                            SpinWaitHelper.SpinWait(sleepTime);
                        }
                    }
                }
                catch (OperationCanceledException) { }

                int[] tmp2;
                while (q.TryDequeue(out tmp2))
                {
                    data.AddRange(tmp2);
                }

                q.CompleteCurrentBatch();
                while (q.TryDequeue(out tmp2))
                {
                    data.AddRange(tmp2);
                }

                lock (global)
                    global.AddRange(data);
            };

            Action enumerateAction = () =>
            {
                Random rnd = new Random();
                while (Volatile.Read(ref addFinished) < thCount && !tokSrc.IsCancellationRequested)
                {
                    int count = 0;
                    foreach (long item in q)
                    {
                        count++;
                    }
                    Thread.Sleep(count > 100 ? 0 : 1);

                    if (rnd.Next(100) == 1)
                    {
                        q.CompleteCurrentBatch();
                    }
                }
            };


            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i] = new Thread(new ThreadStart(takeAction));
            }
            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i] = new Thread(new ThreadStart(addAction));
            }
            enumerateThread = new Thread(new ThreadStart(enumerateAction));

            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i].Start();
            }
            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i].Start();
            }
            enumerateThread.Start();


            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i].Join();
            }
            tokSrc.Cancel();
            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i].Join();
            }
            enumerateThread.Join();


            Assert.AreEqual(elemCount, global.Count);
            global.Sort();

            for (int i = 0; i < elemCount; i++)
            {
                Assert.AreEqual(i, global[i]);
            }
        }
        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));
        }
示例#29
0
        public static void RunTest()
        {
            //TstBQ();

            //Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1;
            SpinWaitHelper.WaitUntilNormalizationCoefCalculated();
            Console.WriteLine($"SpinWait norm coef = {SpinWaitHelper.NormalizationCoef}");


            for (int i = 0; i < 10; i++)
            {
                RunConcurrentBC("1, 1", 5000000, 1, 1, 20, 20);
                Free();

                RunConcurrentBC("4, 4", 5000000, 4, 4, 20, 20);
                Free();

                RunConcurrentBC("16, 1", 5000000, 16, 1, 20, 20);
                Free();

                RunConcurrentBC("1, 16", 5000000, 1, 16, 20, 20);
                Free();

                RunConcurrentBC("16, 16", 5000000, 16, 16, 20, 20);
                Free();

                Console.WriteLine();

                RunConcurrentBQ("1, 1", 5000000, 1, 1, 20, 20);
                Free();

                RunConcurrentBQ("4, 4", 5000000, 4, 4, 20, 20);
                Free();

                RunConcurrentBQ("16, 1", 5000000, 16, 1, 20, 20);
                Free();

                RunConcurrentBQ("1, 16", 5000000, 1, 16, 20, 20);
                Free();

                RunConcurrentBQ("16, 16", 5000000, 16, 16, 20, 20);
                Free();

                Console.WriteLine();

                RunConcurrentCondVar("1, 1", 5000000, 1, 1, 20, 20);
                Free();

                RunConcurrentCondVar("4, 4", 5000000, 4, 4, 20, 20);
                Free();

                RunConcurrentCondVar("16, 1", 5000000, 16, 1, 20, 20);
                Free();

                RunConcurrentCondVar("1, 16", 5000000, 1, 16, 20, 20);
                Free();

                RunConcurrentCondVar("16, 16", 5000000, 16, 16, 20, 20);
                Free();

                Console.WriteLine();

                RunConcurrentMon("1, 1", 5000000, 1, 1, 20, 20);
                Free();

                RunConcurrentMon("4, 4", 5000000, 4, 4, 20, 20);
                Free();

                RunConcurrentMon("16, 1", 5000000, 16, 1, 20, 20);
                Free();

                RunConcurrentMon("1, 16", 5000000, 1, 16, 20, 20);
                Free();

                RunConcurrentMon("16, 16", 5000000, 16, 16, 20, 20);
                Free();

                //RunConcurrentBC("Simple", 5000000, /*Environment.ProcessorCount */ 2, 2, 10, 100);//100 / Environment.ProcessorCount, 101);
                //Free();

                //RunConcurrentBQ("Simple", 5000000, /*Environment.ProcessorCount */ 2, 2, 10, 100);//100 / Environment.ProcessorCount, 101);
                //Free();


                //RunConcurrentBC("OverConcurrency", 5000000, /*4 * Environment.ProcessorCount*/ 8, 8, 0, 0);//100 / Environment.ProcessorCount, 101);
                //Free();

                //RunConcurrentBQ("OverConcurrency", 5000000, /*4 * Environment.ProcessorCount*/ 8, 8, 0, 0);//100 / Environment.ProcessorCount, 101);
                //Free();


                //RunConcurrentBC("OverConcurrency fix", 5000000, /*4 * Environment.ProcessorCount*/ 16, 16, 0, 0);
                //Free();

                //RunConcurrentBQ("OverConcurrency fix", 5000000, /*4 * Environment.ProcessorCount*/ 16, 16, 0, 0);
                //Free();


                Console.WriteLine();
            }
        }
示例#30
0
        private void RunComplexTest(SemaphoreLight sem, int elemCount, int thCount)
        {
            int atomicRandom = 0;

            int trackElemCount   = elemCount;
            int waitedTimesCount = 0;
            int addFinished      = 0;

            Thread[] threadsTake = new Thread[thCount];
            Thread[] threadsAdd  = new Thread[thCount];

            CancellationTokenSource tokSrc = new CancellationTokenSource();

            Action addAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2);

                while (true)
                {
                    int item = Interlocked.Decrement(ref trackElemCount);
                    if (item < 0)
                    {
                        break;
                    }

                    sem.Release();

                    int sleepTime = rnd.Next(12);
                    if (sleepTime > 0)
                    {
                        SpinWaitHelper.SpinWait(sleepTime);
                    }
                }

                Interlocked.Increment(ref addFinished);
            };


            Action takeAction = () =>
            {
                Random rnd = new Random(Environment.TickCount + Interlocked.Increment(ref atomicRandom) * thCount * 2);

                try
                {
                    while (Volatile.Read(ref addFinished) < thCount)
                    {
                        sem.Wait(tokSrc.Token);
                        Interlocked.Increment(ref waitedTimesCount);

                        int sleepTime = rnd.Next(12);
                        if (sleepTime > 0)
                        {
                            SpinWaitHelper.SpinWait(sleepTime);
                        }
                    }
                }
                catch (OperationCanceledException) { }

                TestContext.WriteLine("One take thread exit main cycle");

                while (sem.Wait(0))
                {
                    Interlocked.Increment(ref waitedTimesCount);
                }
            };


            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i] = new Thread(new ThreadStart(takeAction));
            }
            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i] = new Thread(new ThreadStart(addAction));
            }


            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i].Start();
            }
            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i].Start();
            }

            TestContext.WriteLine("All threads started");

            for (int i = 0; i < threadsAdd.Length; i++)
            {
                threadsAdd[i].Join();
            }

            TestContext.WriteLine("All add threads stopped");

            tokSrc.Cancel();

            TestContext.WriteLine("Cancell called");

            for (int i = 0; i < threadsTake.Length; i++)
            {
                threadsTake[i].Join();
            }

            TestContext.WriteLine("All take threads stopped");


            Assert.AreEqual(elemCount, waitedTimesCount);
        }