コード例 #1
0
        /// <summary>
        /// Добавить элемент в стек
        /// </summary>
        /// <param name="element">Элемент</param>
        public void Add(PoolElementWrapper <T> element)
        {
            TurboContract.Requires(element != null, conditionString: "element != null");
            TurboContract.Requires(element.ThisIndex >= 0, conditionString: "element.ThisIndex >= 0");
            TurboContract.Requires(element.ThisIndex < (1 << 16), conditionString: "element.ThisIndex < (1 << 16)");
            TurboContract.Requires(element.NextIndex < 0, conditionString: "element.NextIndex < 0");

            TurboContract.Assert(element.ThisIndex == DataArray.IndexOf(element), conditionString: "element.ThisIndex == DataArray.IndexOf(element)");

            var headIndexOp = _headIndexOp;

            element.NextIndex = GetHeadIndex(headIndexOp);
            if (Interlocked.CompareExchange(ref _headIndexOp, Repack(element.ThisIndex, headIndexOp), headIndexOp) == headIndexOp)
            {
                return;
            }


            AddCore(element);
        }
コード例 #2
0
        /// <summary>
        /// Добавить элемент в стек
        /// </summary>
        /// <param name="element">Элемент</param>
        public void Add(PoolElementWrapper <T> element)
        {
            Contract.Requires(element != null);
            Contract.Requires(element.ThisIndex >= 0);
            Contract.Requires(element.ThisIndex < (1 << 16));
            Contract.Requires(element.NextIndex < 0);

            Debug.Assert(element.ThisIndex == DataArray.IndexOf(element));

            var headIndexOp = _headIndexOp;

            element.NextIndex = GetHeadIndex(headIndexOp);
            if (Interlocked.CompareExchange(ref _headIndexOp, Repack(element.ThisIndex, headIndexOp), headIndexOp) == headIndexOp)
            {
                return;
            }


            AddCore(element);
        }
コード例 #3
0
        /// <summary>
        /// Выполнить удаление элемента из контейнера
        /// </summary>
        /// <param name="element">Элемент</param>
        private void PerformRealRemove(PoolElementWrapper <T> element)
        {
            TurboContract.Requires(element != null, conditionString: "element != null");
            TurboContract.Requires(element.Owner == this, conditionString: "element.Owner == this");
            TurboContract.Requires(element.IsBusy, conditionString: "element.IsBusy");

            if (element.IsRemoved)
            {
                return;
            }

            TurboContract.Assert(element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity, conditionString: "element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity");
            TurboContract.Assert(object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex]), conditionString: "object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex])");

            bool removeResult = _allElements.RemoveAt(element.ThisIndex);

            TurboContract.Assert(removeResult == true, conditionString: "removeResult == true");
            TurboContract.Assert(_allElements.IndexOf(element) < 0, conditionString: "_allElements.IndexOf(element) < 0");
            element.MarkRemoved();
            _allElements.Compact(false);
        }
コード例 #4
0
        /// <summary>
        /// Попробовать забрать элемент из стека
        /// </summary>
        /// <param name="element">Вытянутый элемент</param>
        /// <returns>Успешность</returns>
        public bool TryTake(out PoolElementWrapper <T> element)
        {
            var headIndexOp = _headIndexOp;

            if (GetHeadIndex(headIndexOp) < 0)
            {
                element = null;
                return(false);
            }

            var headElem = _dataArray.GetItemSafe(GetHeadIndex(headIndexOp));

            if (headElem != null && Interlocked.CompareExchange(ref _headIndexOp, Repack(headElem.NextIndex, headIndexOp), headIndexOp) == headIndexOp)
            {
                element           = headElem;
                element.NextIndex = -1;
                return(true);
            }

            return(TryTakeCore(out element));
        }
コード例 #5
0
        /// <summary>
        /// Основной код выборки худшего элемента
        /// </summary>
        /// <param name="element">Выбранный элемент</param>
        /// <returns>Успешность</returns>
        private bool TryTakeWorstCore(out PoolElementWrapper <T> element)
        {
            if (TryTakeWorst(out element))
            {
                return(true);
            }

            lock (_syncObject)
            {
                int tryCount = 0;
                while (true)
                {
                    if (TryTakeWorst(out element))
                    {
                        return(true);
                    }

                    TurboContract.Assert(tryCount++ < 1000, conditionString: "tryCount++ < 1000");
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Выполнить удаление элемента из контейнера
        /// </summary>
        /// <param name="element">Элемент</param>
        private void PerformRealRemove(PoolElementWrapper <T> element)
        {
            Contract.Requires(element != null);
            Contract.Requires(element.Owner == this);
            Contract.Requires(element.IsBusy);

            if (element.IsRemoved)
            {
                return;
            }

            Debug.Assert(element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity);
            Debug.Assert(object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex]));

            bool removeResult = _allElements.RemoveAt(element.ThisIndex);

            Debug.Assert(removeResult == true);
            Debug.Assert(_allElements.IndexOf(element) < 0);
            element.MarkRemoved();
            _allElements.Compact(false);
        }
コード例 #7
0
        /// <summary>
        /// Основной код выборки худшего элемента
        /// </summary>
        /// <param name="element">Выбранный элемент</param>
        /// <returns>Успешность</returns>
        private bool TryTakeWorstCore(out PoolElementWrapper <T> element)
        {
            if (TryTakeWorst(out element))
            {
                return(true);
            }

            lock (_syncObject)
            {
                int tryCount = 0;
                while (true)
                {
                    if (TryTakeWorst(out element))
                    {
                        return(true);
                    }

                    Debug.Assert(tryCount++ < 1000);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Releases element back to the pool. Normally should be called from <see cref="RentedElementMonitor{TElem}"/>
        /// </summary>
        /// <param name="element">Element wrapper to be released</param>
        protected internal sealed override void ReleaseElement(PoolElementWrapper <TElem> element)
        {
            TurboContract.Requires(element != null, conditionString: "element != null");

            if (!element.IsBusy)
            {
                throw new InvalidOperationException("Trying to release same element several times in Pool: " + this.Name);
            }

            _usedElementTracker.UpdateState();

            bool doTrim  = _elementsContainer.Count > _minElementCount && _usedElementTracker.RequestElementToDestroy();
            bool isValid = this.IsValidElement(element.Element);

            if (_disposeCancellation.IsCancellationRequested || !isValid)
            {
                DestroyAndRemoveElement(element);
            }
            else
            {
                _elementsContainer.Release(element);

                if (_disposeCancellation.IsCancellationRequested || doTrim)
                {
                    TakeDestroyAndRemoveElement();
                }
            }

            if (_disposeCancellation.IsCancellationRequested && _elementsContainer.Count == 0)
            {
                _stoppedEvent.Set();
            }

            if (!isValid)
            {
                Profiling.Profiler.ObjectPoolElementFaulted(this.Name, this.ElementCount);
            }

            Profiling.Profiler.ObjectPoolElementReleased(this.Name, this.RentedElementCount);
        }
コード例 #9
0
        /// <summary>
        /// Destroys element and removes it from the Pool
        /// </summary>
        /// <param name="element">Element</param>
        private void DestroyAndRemoveElement(PoolElementWrapper <TElem> element)
        {
            TurboContract.Requires(element != null, conditionString: "element != null");
            TurboContract.Requires(element.IsBusy, conditionString: "element.IsBusy");
            TurboContract.Requires(!element.IsElementDestroyed, conditionString: "!element.IsElementDestroyed");

            try
            {
                this.DestroyElement(element.Element);
                element.MarkElementDestroyed();
            }
            finally
            {
                if (element.IsElementDestroyed)
                {
                    Interlocked.Decrement(ref _reservedCount);
                }

                _elementsContainer.Release(element);
            }

            Profiling.Profiler.ObjectPoolElementDestroyed(this.Name, this.ElementCount);
        }
コード例 #10
0
        private bool TryTakeCore(out PoolElementWrapper <T> element)
        {
            LinearSpinWait sw          = new LinearSpinWait(87, 11);
            var            headIndexOp = _headIndexOp;

            while (GetHeadIndex(headIndexOp) >= 0)
            {
                var headElem = _dataArray.GetItemSafe(GetHeadIndex(headIndexOp));
                if (headElem != null && Interlocked.CompareExchange(ref _headIndexOp, Repack(headElem.NextIndex, headIndexOp), headIndexOp) == headIndexOp)
                {
                    element           = headElem;
                    element.NextIndex = -1;
                    return(true);
                }

                sw.SpinOnce();

                headIndexOp = _headIndexOp;
            }

            element = null;
            return(false);
        }
コード例 #11
0
        // ========================= Take Worst ==================


        /// <summary>
        /// Найти худший элемент в контейнере
        /// </summary>
        /// <returns>Худший элемент, если есть</returns>
        private PoolElementWrapper <T> FindWorst()
        {
            PoolElementWrapper <T> worstItem = null;
            bool stopHere = false;

            var rawItems = _allElements.RawData;

            for (int i = 0; i < rawItems.Length; i++)
            {
                var curItem = Volatile.Read(ref rawItems[i]);
                if (curItem == null || curItem.IsBusy)
                {
                    continue;
                }

                if (worstItem == null || _comparer.Compare(curItem, worstItem, out stopHere) < 0)
                {
                    worstItem = curItem;
                }
            }

            return(worstItem);
        }
コード例 #12
0
        /// <summary>
        /// Обработать свободные элементы (забирает, обрабатывает, возвращает)
        /// </summary>
        /// <param name="action">Действие</param>
        public void ProcessFreeElements(Action <PoolElementWrapper <T> > action)
        {
            TurboContract.Requires(action != null, conditionString: "action != null");

            List <PoolElementWrapper <T> > takenElems = new List <PoolElementWrapper <T> >(_allElements.Count + 1);

            try
            {
                PoolElementWrapper <T> tmp = null;
                while (this.TryTakeInner(out tmp, 0, new CancellationToken()))
                {
                    takenElems.Add(tmp);
                    action(tmp);
                }
            }
            finally
            {
                foreach (var elem in takenElems)
                {
                    this.Release(elem);
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Вернуть элемент в список свободных
        /// </summary>
        /// <param name="element">Элемент</param>
        public void Release(PoolElementWrapper <T> element)
        {
            Contract.Requires(element != null);
            Contract.Requires(element.Owner == this);

            if (element.IsElementDestroyed)
            {
                PerformRealRemove(element);
                element.MakeAvailable();
                return;
            }

            Debug.Assert(element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity);
            Debug.Assert(object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex]));

#pragma warning disable 0420
            _allElements.CompactElementAt(ref element.ThisIndex);
#pragma warning restore 0420

            Debug.Assert(element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity);
            Debug.Assert(object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex]));

            ReleaseCore(element);
        }
コード例 #14
0
        /// <summary>
        /// Вернуть элемент в список свободных
        /// </summary>
        /// <param name="element">Элемент</param>
        public void Release(PoolElementWrapper <T> element)
        {
            TurboContract.Requires(element != null, conditionString: "element != null");
            TurboContract.Requires(element.Owner == this, conditionString: "element.Owner == this");

            if (element.IsElementDestroyed)
            {
                PerformRealRemove(element);
                element.MakeAvailable();
                return;
            }

            TurboContract.Assert(element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity, conditionString: "element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity");
            TurboContract.Assert(object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex]), conditionString: "object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex])");

#pragma warning disable 0420
            _allElements.CompactElementAt(ref element.ThisIndex);
#pragma warning restore 0420

            TurboContract.Assert(element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity, conditionString: "element.ThisIndex >= 0 && element.ThisIndex < _allElements.Capacity");
            TurboContract.Assert(object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex]), conditionString: "object.ReferenceEquals(element, _allElements.RawData[element.ThisIndex])");

            ReleaseCore(element);
        }
コード例 #15
0
        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");
            }
        }
コード例 #16
0
 public override int Compare(PoolElementWrapper <PoolElem> a, PoolElementWrapper <PoolElem> b, out bool stopHere)
 {
     stopHere = false;
     return(0);
 }
コード例 #17
0
 public bool IsValid(PoolElementWrapper <PoolElem> container)
 {
     return(true);
 }
コード例 #18
0
        /// <summary>
        /// Найти 3 лучших элемента с учётом флага раннего останова.
        /// Если выполнилось условие раннего останова, то возвращается элемент, сразу помеченный как busy.
        /// </summary>
        /// <param name="b1">Лучший</param>
        /// <param name="b2">Второй</param>
        /// <param name="b3">Третий</param>
        /// <returns>Захваченный при ранней остановке элемент</returns>
        private PoolElementWrapper <T> FindBest3WithStopping(out PoolElementWrapper <T> b1, out PoolElementWrapper <T> b2, out PoolElementWrapper <T> b3)
        {
            PoolElementWrapper <T> bestItem1 = null;
            PoolElementWrapper <T> bestItem2 = null;
            PoolElementWrapper <T> bestItem3 = null;
            bool stopHere = false;

            var rawItems = _allElements.RawData;

            for (int i = 0; i < rawItems.Length; i++)
            {
                var curItem = Volatile.Read(ref rawItems[i]);
                if (curItem == null || curItem.IsBusy)
                {
                    continue;
                }

                stopHere = false;
                if (bestItem1 == null || _comparer.Compare(curItem, bestItem1, out stopHere) > 0)
                {
                    if (stopHere && curItem.TryMakeBusyAtomic() && !curItem.IsRemoved)
                    {
                        b1 = null;
                        b2 = null;
                        b3 = null;
                        return(curItem);
                    }

                    if (!stopHere)
                    {
                        bestItem3 = bestItem2;
                        bestItem2 = bestItem1;
                        bestItem1 = curItem;
                    }
                }
                else if (bestItem2 == null || _comparer.Compare(curItem, bestItem2, out stopHere) > 0)
                {
                    bestItem3 = bestItem2;
                    bestItem2 = curItem;
                }
                else if (bestItem3 == null || _comparer.Compare(curItem, bestItem2, out stopHere) > 0)
                {
                    bestItem3 = curItem;
                }
            }

            b1 = bestItem1;
            b2 = bestItem2;
            b3 = bestItem3;
            return(null);
        }
コード例 #19
0
 /// <summary>
 /// Выбрать элемент из списка свободных
 /// </summary>
 /// <param name="element">Выбранный элемент</param>
 /// <param name="timeout">Таймаут</param>
 /// <param name="token">Токен отмены</param>
 /// <returns>Успешность</returns>
 public bool TryTake(out PoolElementWrapper <T> element, int timeout, CancellationToken token)
 {
     return(TryTakeWithRemoveInner(out element, timeout, token));
 }
コード例 #20
0
        /// <summary>
        /// Rents element from pool
        /// </summary>
        /// <param name="timeout">Waiting timeout in milliseconds (-1 - infinity)</param>
        /// <param name="token">Token to cancel waiting for element availability</param>
        /// <param name="throwOnUnavail">True - throws <see cref="CantRetrieveElementException"/> when element can't be rented, otherwise returns null</param>
        /// <returns>Wrapper for rented element</returns>
        protected sealed override PoolElementWrapper <TElem> RentElement(int timeout, CancellationToken token, bool throwOnUnavail)
        {
            if (_disposeCancellation.IsCancellationRequested)
            {
                if (throwOnUnavail)
                {
                    throw new CantRetrieveElementException("Rent from pool failed. Dispose was called.", new ObjectDisposedException(this.GetType().Name));
                }

                return(null);
            }

            if (token.IsCancellationRequested)
            {
                if (throwOnUnavail)
                {
                    token.ThrowIfCancellationRequested();
                }

                return(null);
            }


            PoolElementWrapper <TElem> result = null;
            bool elemWasTaken = false;

            if (timeout < 0)
            {
                timeout = Timeout.Infinite;
            }

            CancellationTokenSource linkedTokenSource = null;

            try
            {
                elemWasTaken = _elementsContainer.TryTake(out result, 0, new CancellationToken());

                if (!elemWasTaken && timeout != 0)
                {
                    if (!token.CanBeCanceled)
                    {
                        elemWasTaken = _elementsContainer.TryTake(out result, timeout, _disposeCancellation.Token);
                    }
                    else
                    {
                        linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, _disposeCancellation.Token);
                        elemWasTaken      = _elementsContainer.TryTake(out result, timeout, linkedTokenSource.Token);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
            finally
            {
                if (linkedTokenSource != null)
                {
                    linkedTokenSource.Dispose();
                }
            }


            if (throwOnUnavail && !elemWasTaken)
            {
                if (_disposeCancellation.IsCancellationRequested)
                {
                    // We should attempt to destroy element that was potentially occupied for small amout of time
                    this.TakeDestroyAndRemoveElement();
                    if (_elementsContainer.Count == 0)
                    {
                        _stoppedEvent.Set();
                    }

                    throw new CantRetrieveElementException("Rent from pool failed. Dispose was called.", new ObjectDisposedException(this.GetType().Name));
                }

                token.ThrowIfCancellationRequested();

                if (timeout >= 0)
                {
                    throw new TimeoutException(string.Format("Pool 'Rent' operation has timeouted. Pool: {0}. Timeout value: {1}ms", this.Name, timeout));
                }

                Debug.Assert(false, "Element in pool is not available. Reason: UNKNOWN!");
                throw new CantRetrieveElementException("Rent from pool failed");
            }


            Profiling.Profiler.ObjectPoolElementRented(this.Name, this.RentedElementCount);
            return(result);
        }
コード例 #21
0
 /// <summary>
 /// Checks whether the element is valid and can be used for operations (always true for <see cref="StaticPoolManager{TElem}"/>)
 /// </summary>
 /// <param name="container">Element wrapper</param>
 /// <returns>Whether the element is valid</returns>
 bool IPoolElementOperationSource <TElem> .IsValid(PoolElementWrapper <TElem> container)
 {
     return(true);
 }
コード例 #22
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);
        }
コード例 #23
0
        /// <summary>
        /// Checks whether the element is valid and can be used for operations (redirects call to <see cref="IsValidElement(TElem)"/>)
        /// </summary>
        /// <param name="container">Element wrapper</param>
        /// <returns>Whether the element is valid</returns>
        bool IPoolElementOperationSource <TElem> .IsValid(PoolElementWrapper <TElem> container)
        {
            TurboContract.Requires(container != null, conditionString: "container != null");

            return(this.IsValidElement(container.Element));
        }
コード例 #24
0
 public override int Compare(PoolElementWrapper <int> a, PoolElementWrapper <int> b, out bool stopHere)
 {
     stopHere = false;
     return(a.Element.CompareTo(b.Element));
 }
コード例 #25
0
        /// <summary>
        /// Rents element from pool
        /// </summary>
        /// <param name="timeout">Waiting timeout in milliseconds (-1 - infinity)</param>
        /// <param name="token">Token to cancel waiting for element availability</param>
        /// <param name="throwOnUnavail">True - throws <see cref="CantRetrieveElementException"/> when element can't be rented, otherwise returns null</param>
        /// <returns>Wrapper for rented element</returns>
        protected sealed override PoolElementWrapper <TElem> RentElement(int timeout, System.Threading.CancellationToken token, bool throwOnUnavail)
        {
            if (_disposeCancellation.IsCancellationRequested)
            {
                if (throwOnUnavail)
                {
                    throw new CantRetrieveElementException("Rent from pool failed. Dispose was called.", new ObjectDisposedException(this.GetType().Name));
                }

                return(null);
            }

            if (token.IsCancellationRequested)
            {
                if (throwOnUnavail)
                {
                    token.ThrowIfCancellationRequested();
                }

                return(null);
            }


            if (timeout < 0)
            {
                timeout = Timeout.Infinite;
            }

            PoolElementWrapper <TElem> result            = null;
            CancellationTokenSource    linkedTokenSource = null;

            try
            {
                result = TryGetElement(0, new CancellationToken());

                if (result == null && timeout != 0)
                {
                    if (!token.CanBeCanceled)
                    {
                        result = TryGetElement(timeout, _disposeCancellation.Token);
                    }
                    else
                    {
                        linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, _disposeCancellation.Token);
                        result            = TryGetElement(timeout, linkedTokenSource.Token);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
            finally
            {
                if (linkedTokenSource != null)
                {
                    linkedTokenSource.Dispose();
                }
            }


            // Обновление числа занятых элементов (для удаления неиспользуемых)
            _usedElementTracker.UpdateMinFreeElementCount(this.FreeElementCount);


            if (throwOnUnavail && result == null)
            {
                if (_disposeCancellation.IsCancellationRequested)
                {
                    // We should attempt to destroy element that was potentially occupied for small amout of time
                    this.TakeDestroyAndRemoveElement();
                    if (_elementsContainer.Count == 0)
                    {
                        _stoppedEvent.Set();
                    }

                    throw new CantRetrieveElementException("Rent from pool failed. Dispose was called.", new ObjectDisposedException(this.GetType().Name));
                }

                token.ThrowIfCancellationRequested();

                if (timeout >= 0)
                {
                    throw new TimeoutException(string.Format("Pool 'Rent' operation has timeouted. Pool: {0}. Timeout value: {1}ms", this.Name, timeout));
                }

                TurboContract.Assert(false, "Element in pool is not available. Reason: UNKNOWN!");
                throw new CantRetrieveElementException("Rent from pool failed");
            }


            Profiling.Profiler.ObjectPoolElementRented(this.Name, this.RentedElementCount);
            return(result);
        }
コード例 #26
0
 /// <summary>
 /// Checks whether the element is valid and can be used for operations (redirects call to <see cref="IsValidElement(TElem)"/>)
 /// </summary>
 /// <param name="container">Element wrapper</param>
 /// <returns>Whether the element is valid</returns>
 bool IPoolElementOperationSource <TElem> .IsValid(PoolElementWrapper <TElem> container)
 {
     return(this.IsValidElement(container.Element));
 }
コード例 #27
0
 public int GetPriority(PoolElementWrapper <T> container)
 {
     return(0);
 }
コード例 #28
0
 public bool IsValid(PoolElementWrapper <T> container)
 {
     return(container != null);
 }
コード例 #29
0
 /// <summary>
 /// Compares two elements to choose the best one (a &gt; b =&gt; result &gt; 0; a == b =&gt; result == 0; a &lt; b =&gt; result &lt; 0)
 /// </summary>
 /// <param name="a">First element to compare</param>
 /// <param name="b">Second element to compare</param>
 /// <param name="stopHere">Flag that indicates that the element '<paramref name="a"/>' is sufficient and scanning can be stopped</param>
 /// <returns>Comparison result</returns>
 public override int Compare(PoolElementWrapper <TElem> a, PoolElementWrapper <TElem> b, out bool stopHere)
 {
     return(_objectPool.CompareElements(a.Element, b.Element, out stopHere));
 }
コード例 #30
0
        /// <summary>
        /// Добавить элемент
        /// </summary>
        /// <param name="element">Элемент</param>
        public void Add(PoolElementWrapper <T> element)
        {
            Contract.Requires(element != null);

            _bunches[Thread.CurrentThread.ManagedThreadId % _bunches.Length].Add(element);
        }