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

            Thread th = new Thread(act);

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

            while (Volatile.Read(ref taken) < count)
            {
                SpinWaitHelper.SpinWait(20);
            }
            SpinWaitHelper.SpinWait(rnd.Next(4000));
            th.Abort();
            th.Join();

            if (observedEx != null)
            {
                throw observedEx;
            }
        }
示例#2
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));
        }
        private static TimeSpan MeasureNormalProc(int count, int thCount, int spin)
        {
            int     value    = 0;
            Barrier barStart = new Barrier(thCount + 1);
            Barrier barEnd   = new Barrier(thCount + 1);

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

                while (Interlocked.Increment(ref value) < count)
                {
                    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();
            }

            Console.WriteLine($"Normal. Elapsed = {sw.ElapsedMilliseconds}ms");
            return(sw.Elapsed);
        }
示例#4
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();
         }
     }
 }
示例#5
0
        private void RunTestOnPool(DynamicThreadPool pool, int totalTaskCount, int taskSpinCount, int spawnThreadCount, int spawnSpinTime, bool spawnFromPool)
        {
            Random rndGenerator = new Random();

            int executedTaskCounter = 0;
            int completedTaskCount  = 0;


            Action taskAction = null;

            taskAction = () =>
            {
                int curTaskSpinCount = taskSpinCount;
                lock (rndGenerator)
                    curTaskSpinCount = rndGenerator.Next(taskSpinCount);

                SpinWaitHelper.SpinWait(curTaskSpinCount);

                if (spawnFromPool)
                {
                    if (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount)
                    {
                        pool.Run(taskAction);
                    }
                }

                Interlocked.Increment(ref completedTaskCount);
            };

            Barrier bar = new Barrier(spawnThreadCount + 1);

            Random spawnRndGenerator = new Random();

            Thread[]    spawnThreads = new Thread[spawnThreadCount];
            ThreadStart spawnAction  = () =>
            {
                bar.SignalAndWait();
                while (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount)
                {
                    pool.Run(taskAction);

                    int curSpawnSpinCount = spawnSpinTime;
                    lock (spawnRndGenerator)
                        curSpawnSpinCount = spawnRndGenerator.Next(spawnSpinTime);

                    SpinWaitHelper.SpinWait(curSpawnSpinCount);
                }
            };


            for (int i = 0; i < spawnThreads.Length; i++)
            {
                spawnThreads[i] = new Thread(spawnAction);
            }

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

            bar.SignalAndWait();

            TimingAssert.AreEqual(60 * 1000, totalTaskCount, () => Volatile.Read(ref completedTaskCount));
        }
示例#6
0
        private void RunConcurrentUseWithDispose(int maxPoolElemCount, int threadCount, int opCount, bool faultElements = true)
        {
            using (TestDynamicPool testInst = new TestDynamicPool(0, maxPoolElemCount))
            {
                Thread[] threads  = new Thread[threadCount];
                Barrier  startBar = new Barrier(threadCount + 1);

                int totalExecutedOpCount = 0;

                Action thAct = () =>
                {
                    Random localRand = new Random(Thread.CurrentThread.ManagedThreadId + Environment.TickCount);
                    startBar.SignalAndWait();

                    try
                    {
                        while (true)
                        {
                            int curSpinTime = localRand.Next(0, 2000);

                            Interlocked.Increment(ref totalExecutedOpCount);
                            using (var el = testInst.Rent(60 * 1000, throwOnUnavail: true))
                            {
                                if (faultElements && localRand.Next(10) == 0)
                                {
                                    el.Element.MakeInvalid();
                                }

                                if (curSpinTime > 1000)
                                {
                                    Thread.Sleep(0);
                                }
                                else
                                {
                                    SpinWaitHelper.SpinWait(curSpinTime);
                                }
                            }
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                    }
                    catch (CantRetrieveElementException)
                    {
                    }
                };


                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();


                while (Volatile.Read(ref totalExecutedOpCount) < opCount)
                {
                    Thread.Sleep(1);
                }

                testInst.Dispose();

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

                Assert.AreEqual(testInst.ElementCount, testInst.FreeElementCount, "testInst.ElementCount != testInst.FreeElementCount");
                Assert.AreEqual(testInst.ElementsCreated, testInst.ElementsDestroyed, "ElementsCreated != ElementsDestroyed");
            }
        }
示例#7
0
        private void TestHeavyRandomAddRemoveCore(int operationCount, int threadCount, int spinCount, bool doAutoCompaction)
        {
            SparceArrayStorage <object> testInst = new SparceArrayStorage <object>(doAutoCompaction);
            List <object> activeElements         = new List <object>();
            int           randomSeed             = 0;
            int           operationPerThread     = operationCount / threadCount;

            Thread[] threads = new Thread[threadCount];

            Action act = () =>
            {
                Random        rnd           = new Random(Interlocked.Increment(ref randomSeed) + Environment.TickCount);
                List <object> localElements = new List <object>();

                for (int i = 0; i < operationPerThread; i++)
                {
                    int operationId = doAutoCompaction ? rnd.Next(2) : rnd.Next(3);

                    if (operationId == 0)
                    {
                        object obj = new object();
                        localElements.Add(obj);
                        testInst.Add(obj);
                    }
                    else if (operationId == 1)
                    {
                        if (localElements.Count > 0)
                        {
                            object obj = localElements[rnd.Next(localElements.Count)];
                            localElements.Remove(obj);
                            testInst.Remove(obj);
                        }
                    }
                    else
                    {
                        if (localElements.Count > 0)
                        {
                            object obj             = localElements[rnd.Next(localElements.Count)];
                            int    compactionIndex = testInst.IndexOf(obj);
                            testInst.CompactElementAt(ref compactionIndex);
                        }
                    }

                    int mySpinCount = spinCount / 2 + rnd.Next(spinCount / 2);
                    SpinWaitHelper.SpinWait(mySpinCount);
                }

                lock (activeElements)
                {
                    activeElements.AddRange(localElements);
                }
            };


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

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

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

            Assert.AreEqual(activeElements.Count, testInst.Count, "activeElements.Count != testInst.Count");

            List <object> elementsFromTestInst = new List <object>();

            for (int i = 0; i < testInst.RawData.Length; i++)
            {
                if (testInst.RawData[i] != null)
                {
                    elementsFromTestInst.Add(testInst.RawData[i]);
                }
            }


            Assert.AreEqual(elementsFromTestInst.Count, testInst.Count, "elementsFromTestInst.Count != testInst.Count");

            foreach (var elem in activeElements)
            {
                Assert.IsTrue(elementsFromTestInst.Contains(elem), "!elementsFromTestInst.Contains(elem)");
            }
        }
示例#8
0
        private static TimeSpan TestSemaphoreLight(string name, int elemCount, int addThCount, int takeThCount, int addSpin, int takeSpin)
        {
            SemaphoreLight sem = new SemaphoreLight(0, int.MaxValue);

            CancellationTokenSource srcCancel = new CancellationTokenSource();

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

            int addedElemCount = 0;

            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)
                {
                    sem.Release();
                    SpinWaitHelper.SpinWait(addSpin);
                }

                barierAdders.SignalAndWait();
            };


            Action takeAction = () =>
            {
                CancellationToken myToken = srcCancel.Token;

                barierStart.SignalAndWait();

                try
                {
                    while (!srcCancel.IsCancellationRequested)
                    {
                        sem.Wait(myToken);
                        SpinWaitHelper.SpinWait(takeSpin);
                    }
                }
                catch (OperationCanceledException)
                {
                }

                while (sem.Wait(0))
                {
                }

                barierTakers.SignalAndWait();
            };

            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();
            }

            Console.WriteLine(name + ". SemaphoreLight. Time = " + sw.ElapsedMilliseconds.ToString() + "ms");
            return(sw.Elapsed);
        }
示例#9
0
        private void RunComplexTest(SparceArrayStorage <PoolElementWrapper <int> > storage, IndexedStackElementStorage <int> stack, int elemCount, int thCount)
        {
            int atomicRandom = 0;

            int trackElemCount = elemCount;
            int addFinished    = 0;

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

            CancellationTokenSource tokSrc = new CancellationTokenSource();

            BlockingCollection <PoolElementWrapper <int> > freeElements = new BlockingCollection <PoolElementWrapper <int> >();

            foreach (var elem in storage.RawData)
            {
                if (elem != null)
                {
                    freeElements.Add(elem);
                }
            }

            int[] addedCountArray = new int[storage.Count];
            int[] takenCountArray = new int[storage.Count];


            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;
                    }

                    var elem = freeElements.Take();
                    stack.Add(elem);
                    Interlocked.Increment(ref addedCountArray[storage.IndexOf(elem)]);

                    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)
                    {
                        PoolElementWrapper <int> tmp = null;
                        if (stack.TryTake(out tmp))
                        {
                            freeElements.Add(tmp);
                            Interlocked.Increment(ref takenCountArray[storage.IndexOf(tmp)]);
                        }

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

                PoolElementWrapper <int> tmp2 = null;
                while (stack.TryTake(out tmp2))
                {
                    freeElements.Add(tmp2);
                    Interlocked.Increment(ref takenCountArray[storage.IndexOf(tmp2)]);
                }
            };


            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(storage.Count, freeElements.Count);
            Assert.IsTrue(stack.HeadIndex < 0);

            for (int i = 0; i < storage.Count; i++)
            {
                Assert.IsTrue(addedCountArray[i] == takenCountArray[i], "Added count != taken count");
            }
        }
示例#10
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]);
            }
        }
        // =========================

        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]);
            }
        }
        /// <summary>
        /// Blocks the current thread if it is required
        /// </summary>
        /// <param name="timeout">Waiting timeout in milliseconds</param>
        /// <param name="token">Cancellation token</param>
        /// <returns>True if the current thread successfully passed the <see cref="PartialThreadBlocker"/> (false - exited by timeout)</returns>
        public bool Wait(int timeout, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();
            if (timeout < 0)
            {
                timeout = Timeout.Infinite;
            }

            if (_realWaiterCount >= _expectedWaiterCount)
            {
                return(true);
            }

            if (timeout == 0)
            {
                return(false);
            }

            uint startTime   = 0;
            int  currentTime = Timeout.Infinite;

            if (timeout != Timeout.Infinite)
            {
                startTime = TimeoutHelper.GetTimestamp();
            }

            for (int i = 0; i < 10; i++)
            {
                if (_realWaiterCount >= _expectedWaiterCount)
                {
                    return(true);
                }

                if (i == 5)
                {
                    Thread.Yield();
                }
                else
                {
                    SpinWaitHelper.SpinWait(16 + 4 * i);
                }
            }


            using (CancellationTokenHelper.RegisterWithoutECIfPossible(token, _cancellationTokenCanceledEventHandler, this))
            {
                lock (_lockObj)
                {
                    if (_realWaiterCount < _expectedWaiterCount)
                    {
                        try
                        {
                            _realWaiterCount++;

                            while (_realWaiterCount <= _expectedWaiterCount)
                            {
                                token.ThrowIfCancellationRequested();

                                if (timeout != Timeout.Infinite)
                                {
                                    currentTime = TimeoutHelper.UpdateTimeout(startTime, timeout);
                                    if (currentTime <= 0)
                                    {
                                        return(false);
                                    }
                                }

                                if (!Monitor.Wait(_lockObj, currentTime))
                                {
                                    return(false);
                                }
                            }
                        }
                        finally
                        {
                            _realWaiterCount--;
                        }
                    }
                }
            }
            return(true);
        }
        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));
        }
示例#14
0
        private static TimeSpan RunConcurrentDiskQFile(string name, int elemCount, int addThCount, int takeThCount, int addSpin, int takeSpin)
        {
            if (Directory.Exists("dummy"))
            {
                Directory.Delete("dummy", true);
            }
            Directory.CreateDirectory("dummy");


            DiskQueue <int> col = new DiskQueue <int>("dummy",
                                                      new NonPersistentDiskQueueSegmentFactory <int>(10000, "prefix", new ItemSerializer(), 256, 16),
                                                      10, true);

            //DiskQueue<int> col = new DiskQueue<int>("dummy",
            //    new PersistentDiskQueueSegmentFactory<int>(10000, "prefix", new ItemSerializer(), false, false, 1000, 64),
            //    10, true);

            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 + ". DiskQFile. Time = " + sw.ElapsedMilliseconds.ToString() + "ms");
            }

            col.Dispose();
            return(sw.Elapsed);
        }
示例#15
0
        // ======================

        private void ValidateCountTest(DiskQueue <int> queue, CommonSegmentFactory <int> factory, int elemCount)
        {
            Barrier bar = new Barrier(2);
            CancellationTokenSource cancelled = new CancellationTokenSource();
            List <int> takenElems             = new List <int>(elemCount + 1);
            AtomicBool needSync = new AtomicBool();

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

                bar.SignalAndWait();
                while (curElem < elemCount)
                {
                    bool itemAdded = true;
                    if (rnd.Next(100) == 0)
                    {
                        queue.AddForced(curElem);
                    }
                    else if (needSync.Value)
                    {
                        itemAdded = queue.TryAdd(curElem);
                    }
                    else
                    {
                        queue.Add(curElem);
                    }

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

                    if (itemAdded)
                    {
                        curElem++;
                    }

                    Assert.IsTrue(itemAdded || needSync.Value);

                    if (curElem % 1000 == 0)
                    {
                        needSync.Value = true;
                    }
                    if (needSync.Value && bar.ParticipantsRemaining == 1)
                    {
                        Assert.AreEqual(factory.SumCountFromAllocated(), queue.Count);
                        needSync.Value = false;
                        bar.SignalAndWait();
                    }
                }

                cancelled.Cancel();
            };

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

                bar.SignalAndWait();
                try
                {
                    while (!cancelled.IsCancellationRequested)
                    {
                        takenElems.Add(queue.Take(cancelled.Token));

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

                        if (needSync.Value)
                        {
                            bar.SignalAndWait(cancelled.Token);
                        }
                    }
                }
                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]}");
                }
            }
        }
        private void ConcurrentPackageWithTimeoutTestCore(int addThreads, int itemCount, int batchSize, int boundedCapacityInBatches)
        {
            int atomicRandom = 0;

            BlockingBatchingQueue <int> col = new BlockingBatchingQueue <int>(batchSize: batchSize, boundedCapacityInBatches: boundedCapacityInBatches);
            Barrier bar = new Barrier(1 + 1 + addThreads);
            CancellationTokenSource cancelToken = new CancellationTokenSource();

            Thread[] threadsAdd  = new Thread[addThreads];
            Thread[] threadsTake = new Thread[1];

            List <int> takenItems   = new List <int>();
            int        itemsCounter = itemCount;

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

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

                    col.Add(val);

                    int delay = (int)(((double)val / itemCount) * 100);
                    if (delay > 0)
                    {
                        SpinWaitHelper.SpinWait(rnd.Next(delay));
                    }
                }
            };

            Action takeAction = () =>
            {
                var   token = cancelToken.Token;
                int[] items = null;
                bar.SignalAndWait();


                try
                {
                    while (!cancelToken.IsCancellationRequested)
                    {
                        if (col.TryTake(out items, 5, token))
                        {
                            takenItems.AddRange(items);
                        }
                        else
                        {
                            col.CompleteCurrentBatch();
                        }
                    }
                }
                catch (OperationCanceledException) { }

                while (col.TryTake(out items))
                {
                    takenItems.AddRange(items);
                }

                col.CompleteCurrentBatch();

                if (col.TryTake(out items))
                {
                    takenItems.AddRange(items);
                }
            };

            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();
            }

            bar.SignalAndWait();

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

            cancelToken.Cancel();

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


            takenItems.Sort();
            for (int i = 0; i < takenItems.Count; i++)
            {
                Assert.AreEqual(i, takenItems[i]);
            }
        }
        private void TestCancellationNotCorruptDataCore(int batchSize, int boundedCapacityInBatches)
        {
            BlockingBatchingQueue <long> col = new BlockingBatchingQueue <long>(batchSize: batchSize, boundedCapacityInBatches: boundedCapacityInBatches);
            Barrier bar = new Barrier(4);
            CancellationTokenSource cancelToken              = new CancellationTokenSource();
            CancellationTokenSource temporaryCancelTokenAdd  = new CancellationTokenSource();
            CancellationTokenSource temporaryCancelTokenTake = new CancellationTokenSource();

            List <long> takenItems = new List <long>();

            Task addTask = Task.Run(() =>
            {
                Random rnd = new Random();
                bar.SignalAndWait();
                long data = 0;
                CancellationToken token = temporaryCancelTokenAdd.Token;
                while (!cancelToken.IsCancellationRequested)
                {
                    try
                    {
                        col.Add(data, token);
                        data++;
                    }
                    catch (OperationCanceledException)
                    {
                        token = temporaryCancelTokenAdd.Token;
                    }
                }
            });

            Task takeTask = Task.Run(() =>
            {
                bar.SignalAndWait();

                CancellationToken token = temporaryCancelTokenTake.Token;
                while (!cancelToken.IsCancellationRequested)
                {
                    try
                    {
                        long[] itemsT = col.Take(token);
                        takenItems.AddRange(itemsT);
                    }
                    catch (OperationCanceledException)
                    {
                        token = temporaryCancelTokenTake.Token;
                    }

                    if (takenItems.Count > int.MaxValue / 2)
                    {
                        cancelToken.Cancel();
                    }
                }
            });


            Task cancelTask = Task.Run(() =>
            {
                Random rnd = new Random();
                bar.SignalAndWait();

                while (!cancelToken.IsCancellationRequested)
                {
                    if (rnd.Next(100) == 1)
                    {
                        temporaryCancelTokenAdd.Cancel();
                        temporaryCancelTokenAdd = new CancellationTokenSource();
                    }
                    if (rnd.Next(100) == 1)
                    {
                        temporaryCancelTokenTake.Cancel();
                        temporaryCancelTokenTake = new CancellationTokenSource();
                    }

                    SpinWaitHelper.SpinWait(rnd.Next(12));
                }
            });

            bar.SignalAndWait();
            Thread.Sleep(500);
            cancelToken.Cancel();
            temporaryCancelTokenAdd.Cancel();
            temporaryCancelTokenTake.Cancel();

            Task.WaitAll(addTask, takeTask, cancelTask);

            while (col.TryTake(out long[] itemsF))
            {
                takenItems.AddRange(itemsF);
            }

            col.CompleteCurrentBatch();

            if (col.TryTake(out long[] itemsFF))
            {
                takenItems.AddRange(itemsFF);
            }

            for (int i = 0; i < takenItems.Count; i++)
            {
                Assert.AreEqual(i, takenItems[i]);
            }
        }
示例#18
0
        public void AddTakeSequentialTest()
        {
            const int ItemsCount = 50000;

            var memQueue  = new MemoryQueue <long>();
            var converter = new TypeConverter();

            using (var queue = new TransformationQueue <int, long>(memQueue, converter))
                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++)
                        {
                            if (val % 10 == 0)
                            {
                                queue.Add(val);
                            }
                            else if (val % 10 == 1)
                            {
                                Assert.IsTrue(queue.TryAdd(val));
                            }
                            else if (val % 10 == 2)
                            {
                                Assert.IsTrue(queue.TryAdd(val, 1000));
                            }
                            else if (val % 10 == 3)
                            {
                                Assert.IsTrue(queue.TryAdd(val, TimeSpan.FromSeconds(1)));
                            }
                            else if (val % 10 == 4)
                            {
                                Assert.IsTrue(queue.TryAdd(val, 1000, new CancellationToken()));
                            }
                            else if (val % 10 == 5)
                            {
                                queue.AddForced(val);
                            }
                            else
                            {
                                queue.Add(val, new CancellationToken());
                            }

                            SpinWaitHelper.SpinWait(val % 16);
                        }
                    });

                    var task2 = Task.Run(() =>
                    {
                        barrier.SignalAndWait();
                        for (int val = 0; val < ItemsCount; val++)
                        {
                            int res = 0;
                            if (val % 10 == 0)
                            {
                                Assert.IsTrue(queue.TryTake(out res, 10000), "Value was expected 1");
                            }
                            else if (val % 10 == 1)
                            {
                                Assert.IsTrue(queue.TryTake(out res, 10000, new CancellationToken()), "Value was expected 2");
                            }
                            else
                            {
                                Assert.IsTrue(queue.TryTake(out res, TimeSpan.FromSeconds(10)), "Value was expected 3");
                            }

                            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]");
                    }

                    Assert.AreEqual(0, memQueue.Count);
                    Assert.AreEqual(ItemsCount, converter.ConvertNum);
                    Assert.AreEqual(ItemsCount, converter.ConvertBackNum);
                }
        }
        private void RunThreadPoolConcurrentQueueTest(ThreadPoolConcurrentQueue q, int elemCount, int thCount)
        {
            int atomicRandom = 0;

            int trackElemCount = elemCount;
            int addFinished    = 0;

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

            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.Add(new TestThreadPoolItem(item));

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

                Interlocked.Increment(ref addFinished);
            };

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

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

                while (Volatile.Read(ref addFinished) < thCount)
                {
                    ThreadPoolWorkItem tmp;
                    if (q.TryTake(out tmp))
                    {
                        data.Add((TestThreadPoolItem)tmp);
                    }

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

                ThreadPoolWorkItem tmp2;
                while (q.TryTake(out tmp2))
                {
                    data.Add((TestThreadPoolItem)tmp2);
                }

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


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

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


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


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


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

            for (int i = 0; i < elemCount; i++)
            {
                Assert.AreEqual(i, global[i]);
            }
        }
示例#20
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}'");
                }
            }
        }
示例#21
0
        private void RunComplexTestOnCustom(int threadCount, int queueSize, int testElemCount, int addThreadCount, int procSpinWaitCount, int addSleepMs)
        {
            List <int> processedItems = new List <int>(testElemCount + 1);
            int        currentItem    = 0;
            Random     rnd            = new Random();

            MemoryQueue <int>   mem1 = new MemoryQueue <int>(100);
            MemoryQueue <int>   mem2 = new MemoryQueue <int>(queueSize);
            LevelingQueue <int> lvl  = new LevelingQueue <int>(mem1, mem2);

            using (DelegateQueueAsyncProcessor <int> proc = new DelegateQueueAsyncProcessor <int>(threadCount, lvl, "name", (elem, token) =>
            {
                int curSpinCount = 0;
                lock (rnd)
                    curSpinCount = rnd.Next(procSpinWaitCount);

                SpinWaitHelper.SpinWait(curSpinCount);

                lock (processedItems)
                    processedItems.Add(elem);
            }))
            {
                Action addAction = () =>
                {
                    while (true)
                    {
                        int curVal = Interlocked.Increment(ref currentItem);
                        if (curVal > testElemCount)
                        {
                            break;
                        }

                        proc.Add(curVal - 1);

                        if (addSleepMs > 0)
                        {
                            SmartSleep(addSleepMs);
                        }
                    }
                };


                Thread[] addThreads = new Thread[addThreadCount];

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

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

                proc.Start();

                Assert.IsTrue(proc.IsWork);

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


                proc.Stop(true, true, true);

                Assert.AreEqual(testElemCount, processedItems.Count);

                processedItems.Sort();
                for (int i = 0; i < processedItems.Count; i++)
                {
                    Assert.AreEqual(i, processedItems[i]);
                }
            }
        }
示例#22
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);
        }
示例#23
0
        private static TimeSpan RunTestOnPool(Qoollo.Turbo.Threading.ThreadPools.ThreadPoolBase pool, TestConfiguration config, bool waitForCompletion = true)
        {
            var    taskActiveTimeDev  = (int)(config.ActiveTaskAvgTime.Ticks / 4);
            var    taskPassiveTimeDev = (int)(config.PassiveTaskAvgTime.Ticks / 4);
            Random rndGenerator       = new Random();

            int executedTaskCounter = 0;
            int completedTaskCount  = 0;


            Action taskAction = null;

            taskAction = () =>
            {
                if (config.PassiveTaskAvgTime > TimeSpan.Zero)
                {
                    TimeSpan taskTime = config.PassiveTaskAvgTime;
                    if (config.UseDeviance)
                    {
                        lock (rndGenerator)
                            taskTime += TimeSpan.FromTicks(rndGenerator.Next(-taskPassiveTimeDev, taskPassiveTimeDev));
                    }

                    int taskTimeMs = CalcRandSleep(rndGenerator, taskTime.TotalMilliseconds);

                    if (taskTimeMs > 0)
                    {
                        Thread.Sleep(taskTimeMs);
                    }
                    else if (taskTimeMs == 0)
                    {
                        Thread.Yield();
                    }
                }

                // ----
                if (config.ActiveTaskAvgTime > TimeSpan.Zero)
                {
                    TimeSpan taskTime = config.ActiveTaskAvgTime;
                    if (config.UseDeviance)
                    {
                        lock (rndGenerator)
                            taskTime += TimeSpan.FromTicks(rndGenerator.Next(-taskActiveTimeDev, taskActiveTimeDev));
                    }

                    int taskTimeMs = CalcRandSleep(rndGenerator, taskTime.TotalMilliseconds);

                    if (taskTimeMs > 0)
                    {
                        Stopwatch sw111 = Stopwatch.StartNew();
                        while (sw111.ElapsedMilliseconds < taskTimeMs)
                        {
                            SpinWaitHelper.SpinWait(2000);
                        }
                    }
                    else if (taskTimeMs == 0)
                    {
                        Thread.Yield();
                    }
                }

                // ----

                if (config.SpawnFromPool)
                {
                    if (Interlocked.Increment(ref executedTaskCounter) <= config.TaskCount)
                    {
                        //pool.RunAsTask(taskAction);
                        pool.Run(taskAction);
                    }
                }

                Interlocked.Increment(ref completedTaskCount);
            };

            Barrier bar = new Barrier(config.SpawnThreadCount + 1);

            Random spawnRndGenerator = new Random();
            int    spawnTimeDev      = (int)(config.SpawnPeriod.Ticks / 4);

            Thread[]    spawnThreads = new Thread[config.SpawnThreadCount];
            ThreadStart spawnAction  = () =>
            {
                bar.SignalAndWait();

                long expectedSleep = 0;
                long realSleep     = 0;
                int  curSpawned    = 0;
                while ((curSpawned = Interlocked.Increment(ref executedTaskCounter)) <= config.TaskCount)
                {
                    //pool.RunAsTask(taskAction);
                    pool.Run(taskAction);

                    TimeSpan spawnSleep = config.SpawnPeriod;
                    if (config.UseDeviance)
                    {
                        lock (spawnRndGenerator)
                            spawnSleep += TimeSpan.FromTicks(spawnRndGenerator.Next(-spawnTimeDev, spawnTimeDev));
                    }

                    int spawnSleepMs = CalcRandSleep(spawnRndGenerator, spawnSleep.TotalMilliseconds);

                    if (spawnSleepMs > 0)
                    {
                        expectedSleep += spawnSleepMs;

                        int startTick = Environment.TickCount;
                        if (realSleep <= expectedSleep)
                        {
                            Thread.Sleep(spawnSleepMs);
                        }

                        realSleep += (Environment.TickCount - startTick);
                    }
                }
            };


            for (int i = 0; i < spawnThreads.Length; i++)
            {
                spawnThreads[i] = new Thread(spawnAction);
            }

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


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

            if (waitForCompletion)
            {
                SpinWait.SpinUntil(() => Volatile.Read(ref completedTaskCount) >= config.TaskCount);
            }
            else
            {
                SpinWait.SpinUntil(() => Volatile.Read(ref executedTaskCounter) >= config.TaskCount);
            }

            sw.Stop();

            if (waitForCompletion && completedTaskCount != config.TaskCount)
            {
                throw new Exception("completedTaskCount != config.TaskCount");
            }

            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]}");
                }
            }
        }
 public long ConvertBack(int item)
 {
     SpinWaitHelper.SpinWait(8);
     return(item);
 }
示例#26
0
        private void RunComplexTest(ThreadPoolGlobalQueue q, int elemCount, int thCount)
        {
            int atomicRandom = 0;

            int trackElemCount = elemCount;
            int addFinished    = 0;

            Thread[] threadsMain       = new Thread[thCount];
            Thread[] threadsAdditional = new Thread[thCount];

            CancellationTokenSource tokSrc = new CancellationTokenSource();

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

            Action additionalAction = () =>
            {
                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.Add(new TestThreadPoolItem(item));

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

                    if (rnd.Next(100) == 0)
                    {
                        q.RequestCapacityExtension(50);
                    }
                }

                Interlocked.Increment(ref addFinished);
            };


            Action mainAction = () =>
            {
                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)
                    {
                        ThreadPoolWorkItem tmp = null;
                        if (q.TryTake(out tmp, -1, tokSrc.Token, true))
                        {
                            data.Add((TestThreadPoolItem)tmp);
                        }

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

                ThreadPoolWorkItem tmp2;
                while (q.TryTake(out tmp2, 0, CancellationToken.None, true))
                {
                    data.Add((TestThreadPoolItem)tmp2);
                }

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

            Task.Delay(1000).ContinueWith(t => q.RequestCapacityExtension(50));


            for (int i = 0; i < threadsMain.Length; i++)
            {
                threadsMain[i] = new Thread(new ThreadStart(mainAction));
            }
            for (int i = 0; i < threadsAdditional.Length; i++)
            {
                threadsAdditional[i] = new Thread(new ThreadStart(additionalAction));
            }


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


            for (int i = 0; i < threadsAdditional.Length; i++)
            {
                threadsAdditional[i].Join();
            }
            tokSrc.Cancel();
            for (int i = 0; i < threadsMain.Length; i++)
            {
                threadsMain[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(PrioritizedElementsContainer <int> testInst, int threadCount, int opCount, int pauseSpin)
        {
            Assert.AreEqual(testInst.AvailableCount, testInst.Count);

            Thread[] threads  = new Thread[threadCount];
            Barrier  startBar = new Barrier(threadCount + 1);

            int opCountPerThread = opCount / threadCount;

            Action thAct = () =>
            {
                startBar.SignalAndWait();
                TestContext.WriteLine("Inside thread. Signal and wait passed");

                try
                {
                    int execOp = 0;
                    while (execOp++ < opCountPerThread)
                    {
                        PoolElementWrapper <int> item = null;
                        try
                        {
                            item = testInst.Take();
                            //Thread.Sleep(pauseSpin);
                            SpinWaitHelper.SpinWait(pauseSpin);
                        }
                        finally
                        {
                            testInst.Release(item);
                        }
                    }
                }
                catch (Exception ex)
                {
                    TestContext.WriteLine("Unhandled exception: " + ex.ToString());
                    throw;
                }
            };


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

            TestContext.WriteLine("Threads created");

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

            TestContext.WriteLine("Threads started");

            startBar.SignalAndWait();

            TestContext.WriteLine("Threads before join");

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

            TestContext.WriteLine("All threads stopped");

            Assert.AreEqual(testInst.AvailableCount, testInst.Count);
        }
示例#28
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);
        }
示例#29
0
        // ===================

        private void RunComplexTest(MutuallyExclusivePrimitive inst, int workCount, int workSpin, int sleepProbability)
        {
            Barrier barrier = new Barrier(4);
            CancellationTokenSource globalCancellation = new CancellationTokenSource();
            ManualResetEventSlim    alwaysNotSet       = new ManualResetEventSlim(false);
            int workPerformGate1   = 0;
            int workPerformGate2   = 0;
            int workCompletedCount = 0;

            int gate1Executed = 0;
            int gate2Executed = 0;

            Action <Random, CancellationToken, int> doWork = (Random rnd, CancellationToken token, int gate) =>
            {
                try
                {
                    if (gate == 1)
                    {
                        Interlocked.Increment(ref workPerformGate1);
                        if (Volatile.Read(ref workPerformGate2) != 0)
                        {
                            throw new Exception("Mutual exclusive logic is broken");
                        }

                        Interlocked.Increment(ref gate1Executed);
                    }
                    else
                    {
                        Interlocked.Increment(ref workPerformGate2);
                        if (Volatile.Read(ref workPerformGate1) != 0)
                        {
                            throw new Exception("Mutual exclusive logic is broken");
                        }

                        Interlocked.Increment(ref gate2Executed);
                    }

                    if (rnd.Next(sleepProbability) == 0)
                    {
                        alwaysNotSet.Wait(1, token);
                    }
                    else
                    {
                        int spin = rnd.Next(0, workSpin);
                        SpinWaitHelper.SpinWait(spin);
                    }
                }
                finally
                {
                    if (gate == 1)
                    {
                        Interlocked.Decrement(ref workPerformGate1);
                    }
                    else
                    {
                        Interlocked.Decrement(ref workPerformGate2);
                    }
                }
            };


            Action <int> worker = (int gate) =>
            {
                var    token = globalCancellation.Token;
                Random rnd   = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId);

                barrier.SignalAndWait();
                while (!token.IsCancellationRequested)
                {
                    try
                    {
                        using (var guard = gate == 1 ? inst.EnterMain(Timeout.Infinite, token) : inst.EnterBackground(Timeout.Infinite, token))
                        {
                            using (var linked = CancellationTokenSource.CreateLinkedTokenSource(token, guard.Token))
                            {
                                doWork(rnd, token, gate);
                            }
                        }

                        int spin = rnd.Next(0, workSpin);
                        SpinWaitHelper.SpinWait(spin);
                    }
                    catch (OperationCanceledException) { }

                    int localWorkCompl = Interlocked.Increment(ref workCompletedCount);
                    if (localWorkCompl > workCount)
                    {
                        globalCancellation.Cancel();
                    }
                }
            };

            Action switcher = () =>
            {
                var    token = globalCancellation.Token;
                Random rnd   = new Random(Environment.TickCount + Thread.CurrentThread.ManagedThreadId);

                barrier.SignalAndWait();
                while (!token.IsCancellationRequested)
                {
                    int sleep = rnd.Next(workSpin);

                    Thread.Sleep(sleep);
                    inst.AllowBackgroundGate();

                    sleep = rnd.Next(workSpin);
                    Thread.Sleep(sleep);
                    inst.DisallowBackgroundGate();
                }
            };

            Task workerThread1  = Task.Factory.StartNew(() => worker(1), TaskCreationOptions.LongRunning);
            Task workerThread2  = Task.Factory.StartNew(() => worker(2), TaskCreationOptions.LongRunning);
            Task workerThread3  = Task.Factory.StartNew(() => worker(2), TaskCreationOptions.LongRunning);
            Task switcherThread = Task.Factory.StartNew(() => switcher(), TaskCreationOptions.LongRunning);

            Task.WaitAll(workerThread1, workerThread2, workerThread3, switcherThread);

            Assert.IsTrue(gate1Executed > 0);
            Assert.IsTrue(gate2Executed > 0);
        }