/// <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); }
/// <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); }
/// <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); }
/// <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)); }
/// <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"); } } }
/// <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); }
/// <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); } } }
/// <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); }
/// <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); }
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); }
// ========================= 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); }
/// <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); } } }
/// <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); }
/// <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); }
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"); } }
public override int Compare(PoolElementWrapper <PoolElem> a, PoolElementWrapper <PoolElem> b, out bool stopHere) { stopHere = false; return(0); }
public bool IsValid(PoolElementWrapper <PoolElem> container) { return(true); }
/// <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); }
/// <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)); }
/// <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); }
/// <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); }
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); }
/// <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)); }
public override int Compare(PoolElementWrapper <int> a, PoolElementWrapper <int> b, out bool stopHere) { stopHere = false; return(a.Element.CompareTo(b.Element)); }
/// <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); }
/// <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)); }
public int GetPriority(PoolElementWrapper <T> container) { return(0); }
public bool IsValid(PoolElementWrapper <T> container) { return(container != null); }
/// <summary> /// Compares two elements to choose the best one (a > b => result > 0; a == b => result == 0; a < b => result < 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)); }
/// <summary> /// Добавить элемент /// </summary> /// <param name="element">Элемент</param> public void Add(PoolElementWrapper <T> element) { Contract.Requires(element != null); _bunches[Thread.CurrentThread.ManagedThreadId % _bunches.Length].Add(element); }