public void TestAddTakeCommonCase()
        {
            SparceArrayStorage <PoolElementWrapper <int> > storage = CreateSparceArray(100);
            BunchElementStorage <int> testInst = new BunchElementStorage <int>(storage);

            try
            {
                for (int i = 0; i < storage.Count; i++)
                {
                    testInst.Add(storage.RawData[i]);
                }

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

                for (int i = 0; i < storage.Count; i++)
                {
                    PoolElementWrapper <int> elem = null;
                    testInst.Take(out elem);
                    takenElems.Add(elem.Element);
                }

                Assert.AreEqual(100, takenElems.Count);
                takenElems.Sort();
                for (int i = 0; i < takenElems.Count; i++)
                {
                    Assert.AreEqual(i, takenElems[i]);
                }
            }
            finally
            {
                DestroySparceArray(storage);
            }
        }
        public void TestAddTakeSingleThreadCase()
        {
            SparceArrayStorage <PoolElementWrapper <int> > storage = CreateSparceArray(100);
            BunchElementStorage <int> testInst = new BunchElementStorage <int>(storage);

            try
            {
                for (int i = 0; i < storage.Count; i++)
                {
                    testInst.Add(storage.RawData[i]);
                }


                for (int i = storage.Count - 1; i >= 0; i--)
                {
                    PoolElementWrapper <int> elem = null;
                    testInst.Take(out elem);
                    Assert.AreEqual(i, elem.Element);
                }
            }
            finally
            {
                DestroySparceArray(storage);
            }
        }
        public void TestConcurrentAddTake()
        {
            SparceArrayStorage <PoolElementWrapper <int> > storage = CreateSparceArray(1000);
            BunchElementStorage <int> testInst = new BunchElementStorage <int>(storage);

            try
            {
                RunComplexTest(storage, testInst, 5000000, 1 + Environment.ProcessorCount / 2);
            }
            finally
            {
                DestroySparceArray(storage);
            }
        }
        private void RunComplexTest(SparceArrayStorage <PoolElementWrapper <int> > storage, BunchElementStorage <int> bunchStorage, 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();

            int elementCountInBunchStorage = 0;
            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();
                    bunchStorage.Add(elem);
                    Interlocked.Increment(ref elementCountInBunchStorage);
                    Interlocked.Increment(ref addedCountArray[storage.IndexOf(elem)]);

                    int sleepTime = rnd.Next(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)
                    {
                        int elementCountInBunchStorageLoc = Volatile.Read(ref elementCountInBunchStorage);
                        if (elementCountInBunchStorageLoc > 0 &&
                            Interlocked.CompareExchange(ref elementCountInBunchStorage, elementCountInBunchStorageLoc - 1, elementCountInBunchStorageLoc) == elementCountInBunchStorageLoc)
                        {
                            PoolElementWrapper <int> tmp = null;
                            bunchStorage.Take(out tmp);
                            freeElements.Add(tmp);
                            Interlocked.Increment(ref takenCountArray[storage.IndexOf(tmp)]);
                        }

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

                int elementCountInBunchStorageLoc2 = Volatile.Read(ref elementCountInBunchStorage);
                while (elementCountInBunchStorageLoc2 > 0)
                {
                    if (Interlocked.CompareExchange(ref elementCountInBunchStorage, elementCountInBunchStorageLoc2 - 1, elementCountInBunchStorageLoc2) == elementCountInBunchStorageLoc2)
                    {
                        PoolElementWrapper <int> tmp = null;
                        bunchStorage.Take(out tmp);
                        freeElements.Add(tmp);
                        Interlocked.Increment(ref takenCountArray[storage.IndexOf(tmp)]);
                    }

                    elementCountInBunchStorageLoc2 = Volatile.Read(ref elementCountInBunchStorage);
                }
            };


            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.AreEqual(0, elementCountInBunchStorage);

            for (int i = 0; i < storage.Count; i++)
            {
                Assert.IsTrue(addedCountArray[i] == takenCountArray[i], "Added count != taken count");
            }
        }
Пример #5
0
 /// <summary>
 /// Конструктор SimpleElementsContainer
 /// </summary>
 public SimpleElementsContainer()
 {
     _allElements        = new SparceArrayStorage <PoolElementWrapper <T> >(false);
     _globalFreeElements = new BunchElementStorage <T>(_allElements);
     _occupiedElements   = new SemaphoreLight(0);
 }