Example #1
0
        /// <summary>
        /// Adds new item to the queue, even when the bounded capacity reached
        /// </summary>
        /// <param name="item">New item</param>
        public override void AddForced(T item)
        {
            CheckDisposed();

            if (_addingMode == LevelingQueueAddingMode.PreferLiveData)
            {
                if (!_highLevelQueue.TryAdd(item, 0, default(CancellationToken)))
                {
                    _lowLevelQueue.AddForced(item);

                    if (_isBackgroundTransferingEnabled)
                    {
                        _backgoundTransfererExclusive.AllowBackgroundGate(); // Allow background transfering
                    }
                }
            }
            else
            {
                bool addedToHighLevelQueue = false;
                if (_isBackgroundTransferingEnabled)
                {
                    if (_lowLevelQueue.IsEmpty)
                    {
                        // Only in exclusive mode
                        using (var gateGuard = _backgoundTransfererExclusive.EnterMain(Timeout.Infinite, default(CancellationToken))) // This should happen fast
                        {
                            TurboContract.Assert(gateGuard.IsAcquired, conditionString: "gateGuard.IsAcquired");
                            addedToHighLevelQueue = _lowLevelQueue.IsEmpty && _highLevelQueue.TryAdd(item, 0, default(CancellationToken));
                        }
                    }
                }
                else
                {
                    addedToHighLevelQueue = _lowLevelQueue.IsEmpty && _highLevelQueue.TryAdd(item, 0, default(CancellationToken));
                }

                if (!addedToHighLevelQueue)
                {
                    _lowLevelQueue.AddForced(item);
                    if (_isBackgroundTransferingEnabled)
                    {
                        _backgoundTransfererExclusive.AllowBackgroundGate(); // Allow background transfering
                    }
                }
            }

            NotifyItemAdded();
        }
        // ============================

        private void PreserveOrderTest(IQueue <long> 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
                    {
                        Assert.IsTrue(queue.TryAdd(curElem, -1, default(CancellationToken)));
                    }

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

                    curElem++;
                }

                cancelled.Cancel();
            };

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

                bar.SignalAndWait();
                try
                {
                    while (!cancelled.IsCancellationRequested)
                    {
                        long itemX = 0;
                        Assert.IsTrue(queue.TryTake(out itemX, -1, cancelled.Token));
                        takenElems.Add((int)itemX);

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

                long item = 0;
                while (queue.TryTake(out item, 0, default(CancellationToken)))
                {
                    takenElems.Add((int)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 RunComplexTest(IQueue <long> q, int elemCount, int addSpin, int takeSpin, 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();

            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)
                    {
                        q.AddForced(item);
                    }
                    else
                    {
                        Assert.IsTrue(q.TryAdd(item, -1, default(CancellationToken)));
                    }


                    int sleepTime = rnd.Next(addSpin);

                    long tmpItem = 0;
                    if (q.TryPeek(out tmpItem, 0, default(CancellationToken)) && tmpItem % 1000 == 0)
                    {
                        sleepTime += 100;
                    }

                    if (sleepTime > 0)
                    {
                        Thread.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)
                    {
                        long tmp = 0;
                        if (q.TryTake(out tmp, -1, tokSrc.Token))
                        {
                            data.Add((int)tmp);
                        }

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

                long tmp2;
                while (q.TryTake(out tmp2, 0, default(CancellationToken)))
                {
                    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]);
            }
        }
Example #4
0
 /// <summary>
 /// Adds new item to the high level queue, even when the bounded capacity reached
 /// </summary>
 /// <param name="item">New item</param>
 public void AddForcedToHighLevelQueue(T item)
 {
     CheckDisposed();
     _highLevelQueue.AddForced(item);
     NotifyItemAdded();
 }