예제 #1
0
        // ==========================

        private void StableIsEmptyAndCountTest(bool ord, bool bcg)
        {
            const int ItemCount = 100000;

            MemoryQueue <int> high = new MemoryQueue <int>();
            MemoryQueue <int> low  = new MemoryQueue <int>();

            for (int i = 0; i < ItemCount + 1; i++)
            {
                low.Add(i);
            }

            using (var q = new LevelingQueue <int>(high, low, ord ? LevelingQueueAddingMode.PreserveOrder : LevelingQueueAddingMode.PreferLiveData, bcg))
            {
                Assert.AreEqual(ItemCount + 1, q.Count);
                if (bcg && !ord)
                {
                    q.Take();
                }
                else
                {
                    Assert.AreEqual(0, q.Take());
                }

                int startTime = Environment.TickCount;
                while (!low.IsEmpty && (Environment.TickCount - startTime) < 500)
                {
                    Assert.AreEqual(ItemCount, q.Count);
                    Assert.IsFalse(q.IsEmpty);
                }
            }
        }
예제 #2
0
        public void BacgroundTransferingWorksNonOrdBcg()
        {
            MemoryQueue <int> high = new MemoryQueue <int>(10);
            MemoryQueue <int> low  = new MemoryQueue <int>(10);

            high.Add(1);
            while (low.TryAdd(low.Count + 2))
            {
                ;
            }

            using (var inst = new LevelingQueue <int>(high, low, LevelingQueueAddingMode.PreferLiveData, true))
            {
                Assert.AreEqual(1, inst.Take());

                TimingAssert.AreEqual(10000, 10, () => high.Count);
                Assert.AreEqual(0, low.Count);

                int item     = 0;
                int expected = 2;
                while (inst.TryTake(out item))
                {
                    Assert.AreEqual(expected++, item);
                }
            }
        }
예제 #3
0
        // ===============

        private void AddTakeTest(LevelingQueue <int> queue, int bound)
        {
            Assert.AreEqual(bound, queue.BoundedCapacity);
            Assert.AreEqual(0, queue.Count);
            Assert.IsTrue(queue.IsEmpty);

            queue.Add(-1);
            Assert.AreEqual(1, queue.Count);
            Assert.IsFalse(queue.IsEmpty);

            int peekVal = queue.Peek();

            Assert.AreEqual(-1, peekVal);
            Assert.AreEqual(1, queue.Count);
            Assert.IsFalse(queue.IsEmpty);

            int takeVal = queue.Take();

            Assert.AreEqual(-1, takeVal);
            Assert.AreEqual(0, queue.Count);
            Assert.IsTrue(queue.IsEmpty);

            int itemCount = 1;

            while (queue.TryAdd(itemCount))
            {
                itemCount++;
            }
            itemCount--;

            Assert.AreEqual(itemCount, queue.Count);
            Assert.IsFalse(queue.IsEmpty);

            queue.AddForced(++itemCount);
            Assert.AreEqual(itemCount, queue.Count);

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

            while (queue.TryTake(out takeVal))
            {
                takenItems.Add(takeVal);
                Assert.AreEqual(itemCount - takenItems.Count, queue.Count);
            }

            Assert.AreEqual(itemCount, takenItems.Count, "count diff");
            Assert.IsTrue(queue.IsEmpty);

            if (queue.AddingMode != LevelingQueueAddingMode.PreserveOrder)
            {
                takenItems.Sort();
            }

            for (int i = 0; i < takenItems.Count; i++)
            {
                Assert.AreEqual(i + 1, takenItems[i]);
            }
        }
예제 #4
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();
        }
예제 #5
0
        private static TimeSpan RunConcurrentLvlQ(string name, int elemCount, int addThCount, int takeThCount, int addSpin, int takeSpin)
        {
            LevelingQueue <int> col = new LevelingQueue <int>(
                new MemoryQueue <int>(3000),
                //new MemoryQueue<int>(7000),
                new LevelingQueue <int>(new MemoryQueue <int>(3000), new MemoryQueue <int>(4000), LevelingQueueAddingMode.PreferLiveData, true),
                LevelingQueueAddingMode.PreserveOrder, false);

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

            col.Dispose();
            return(sw.Elapsed);
        }
예제 #6
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}'");
                }
            }
        }