/// <summary> /// Получить или создать данные для текущего потока. /// Предполагается, что вызывающий поток принадлежит пулу потоков /// </summary> /// <param name="createThreadLocalQueue">Создавать ли локальную очередь потока</param> /// <returns>Данные потока</returns> public ThreadPoolThreadLocals GetOrCreateThisThreadData(bool createThreadLocalQueue = true) { TurboContract.Ensures(TurboContract.Result <ThreadPoolThreadLocals>() != null); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); ThreadPoolThreadLocals result = _perThreadData.Value; if (result == null) { result = new ThreadPoolThreadLocals(this, createThreadLocalQueue); _perThreadData.Value = result; if (createThreadLocalQueue) { _queues.AddLocalQueue(result.LocalQueue); } } return(result); }
/// <summary> /// Scans a range of types with attributes and execute 'procAction' for every that passed the filter /// </summary> /// <typeparam name="TAttr">The type of the attribute that is used to mark a type (should be derived from LocatorTargetObjectAttribute)</typeparam> /// <param name="typeSource">The sequence of all types to scan</param> /// <param name="attrCmpPredicate">Predicate that allows to filter out non relevant types (can be null)</param> /// <param name="procAction">Action executed for every type</param> /// <param name="multiAttr">Allows processing of multiple attributes on the same type</param> protected void ScanTypeRangeWithStrictAttr <TAttr>(IEnumerable <Type> typeSource, Func <TAttr, bool> attrCmpPredicate, Action <Type, TAttr> procAction, bool multiAttr = true) where TAttr : LocatorTargetObjectAttribute { if (typeSource == null) { throw new ArgumentNullException(nameof(typeSource)); } if (procAction == null) { throw new ArgumentNullException(nameof(procAction)); } CheckContainerState(true); object[] attr = null; foreach (var curTp in typeSource) { TurboContract.Assert(curTp != null, conditionString: "curTp != null"); attr = curTp.GetCustomAttributes(false); if (attr == null || attr.Length == 0) { continue; } foreach (var curAttr in attr.OfType <TAttr>()) { TurboContract.Assert(curAttr != null, conditionString: "curAttr != null"); if (attrCmpPredicate == null || attrCmpPredicate(curAttr)) { procAction(curTp, curAttr); if (!multiAttr) { break; } } } } }
/// <summary> /// Выбрать худший элемент из списка свободных /// </summary> /// <param name="element">Выбранный элемент</param> /// <param name="timeout">Таймаут</param> /// <param name="token">Токен отмены</param> /// <returns>Успешность</returns> private bool TryTakeWorstInner(out PoolElementWrapper <T> element, int timeout, CancellationToken token) { element = null; if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } bool waitForSemaphoreWasSuccessful = _occupiedElements.Wait(0); if (waitForSemaphoreWasSuccessful == false && timeout != 0) { waitForSemaphoreWasSuccessful = _occupiedElements.Wait(timeout, token); } if (!waitForSemaphoreWasSuccessful) { return(false); } bool removeSucceeded = false; bool removeFaulted = true; try { //token.ThrowIfCancellationRequested(); // TODO: Refactor the code removeSucceeded = this.TryTakeWorstCore(out element); TurboContract.Assert(removeSucceeded, "Take from underlying collection return false"); removeFaulted = false; } finally { if (!removeSucceeded && removeFaulted) { _occupiedElements.Release(); } } return(removeSucceeded); }
/// <summary> /// Increases the number of threads that should be blocked /// </summary> /// <param name="addValue">The value by which it is necessary to increase the number of blocked threads</param> /// <returns>Updated value stored in <see cref="ExpectedWaiterCount"/></returns> public int AddExpectedWaiterCount(int addValue) { SpinWait sw = new SpinWait(); int expectedWaiterCount = _expectedWaiterCount; TurboContract.Assert(expectedWaiterCount + addValue >= 0, "Negative ExpectedWaiterCount. Can be commented"); int newExpectedWaiterCount = Math.Max(0, expectedWaiterCount + addValue); while (Interlocked.CompareExchange(ref _expectedWaiterCount, newExpectedWaiterCount, expectedWaiterCount) != expectedWaiterCount) { sw.SpinOnce(); expectedWaiterCount = _expectedWaiterCount; TurboContract.Assert(expectedWaiterCount + addValue >= 0, "Negative ExpectedWaiterCount. Can be commented"); newExpectedWaiterCount = Math.Max(0, expectedWaiterCount + addValue); } WakeUpWaiters(newExpectedWaiterCount - expectedWaiterCount); return(newExpectedWaiterCount); }
public bool TryResolve <T>(out T val) { Lifetime.LifetimeBase life = null; if (this.TryGetAssociation(typeof(T), out life)) { TurboContract.Assert(life != null, conditionString: "life != null"); if (life.TryGetInstance(_resolver, out object tmp)) { if (tmp is T) { val = (T)tmp; return(true); } } } val = default(T); return(false); }
/// <summary> /// Notifies specified number of threads about possible state change /// </summary> /// <param name="count">Number of threads to be notified</param> public void Pulse(int count) { if (_waiterCount > 0) { lock (_externalLock) { TurboContract.Assert(_waiterCount >= _waiterQueue.Count, conditionString: "_waiterCount >= _waiterQueue.Count"); for (int i = 0; i < count; i++) { if (_waiterQueue.Count == 0) { break; } var waiter = _waiterQueue.RemoveFirst(); waiter.Set(); } } } }
/// <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> /// Adds new item to the tail of the queue (slow path) /// </summary> /// <returns>Was added sucessufully</returns> private bool TryAddSlow(T item, int timeout, CancellationToken token) { TimeoutTracker timeoutTracker = new TimeoutTracker(timeout); if (timeout != 0 && _addMonitor.WaiterCount > 0) { Thread.Yield(); } // Check WaiterCount to preserve fairness // Check _segments.Count to prevent stucking inside lock if (_addMonitor.WaiterCount == 0 || _segments.Count <= _maxSegmentCount - _nonFairSegmentThreshold) { var tailSegment = TryGetNonFullTailSegment(); if (tailSegment != null && tailSegment.TryAdd(item)) { return(true); } if (timeout == 0 || timeoutTracker.IsTimeouted) { return(false); } } // Use waiting scheme using (var waiter = _addMonitor.Enter(timeoutTracker.RemainingMilliseconds, token)) { do { var tailSegment = TryGetNonFullTailSegment(); if (tailSegment != null && tailSegment.TryAdd(item)) { return(true); } TurboContract.Assert(tailSegment == null || tailSegment.IsFull, conditionString: "tailSegment == null || tailSegment.IsFull"); }while (waiter.Wait()); } return(false); }
/// <summary> /// Read signle item from disk and deserialize it /// </summary> /// <param name="item">Taken item</param> /// <param name="buffer">Buffer</param> /// <param name="take">True = take, False = peek</param> /// <returns>Success or not</returns> private bool TryTakeOrPeekItemFromDisk(out T item, RegionBinaryReader buffer, bool take) { TurboContract.Requires(buffer != null, conditionString: "buffer != null"); TurboContract.Assert(Monitor.IsEntered(_readLock), conditionString: "Monitor.IsEntered(_readLock)"); buffer.BaseStream.SetOriginLength(0, -1); int itemSize = 0; if (!TryTakeOrPeekSingleItemBytesFromDisk(buffer.BaseStream.InnerStream, out itemSize, take)) // Read from disk { item = default(T); return(false); } buffer.BaseStream.SetOriginLength(ItemHeaderSize, itemSize); TurboContract.Assert(buffer.BaseStream.Length == itemSize, conditionString: "buffer.BaseStream.Length == itemSize"); item = _serializer.Deserialize(buffer); // Deserialize return(true); }
/// <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> /// Cleans-up ObjectPool resources /// </summary> /// <param name="isUserCall">Is it called explicitly by user (False - from finalizer)</param> protected override void Dispose(bool isUserCall) { if (isUserCall) { this.DisposePool(false); } else { #if DEBUG var elementsContainer = _elementsContainer; if (elementsContainer == null) { TurboContract.Assert(false, "BalancingDynamicPoolManager should be Disposed by user! PoolName: " + this.Name); } elementsContainer.ProcessFreeElements(o => o.MarkElementDestroyed()); #endif } base.Dispose(isUserCall); }
// ====================== /// <summary> /// Попробовать добавить элемент в очередь /// </summary> /// <param name="item">Элемент</param> /// <param name="localQueue">Локальная очередь потока (если есть)</param> /// <param name="forceGlobal">Обязательное добавление в глобальную очередь</param> /// <param name="timeout">Таймаут</param> /// <param name="token">Токен отмены</param> /// <returns>Удалось ли добавить</returns> public bool TryAdd(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue, bool forceGlobal, int timeout, CancellationToken token) { TurboContract.Requires(item != null, conditionString: "item != null"); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); if (localQueue != null && !forceGlobal) { bool added = false; try { } finally { added = localQueue.TryAddLocal(item); } if (added) { return(true); } } return(_globalQueue.TryAdd(item, timeout, token)); }
/// <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> /// Pool clean-up (core method) /// </summary> /// <param name="waitForRelease">Should it wait for full completion</param> private void DisposePool(bool waitForRelease) { if (!_disposeCancellation.IsCancellationRequested) { #if DEBUG _elementsContainer.ProcessAllElements(o => o.SetPoolDisposed()); #endif _disposeCancellation.Cancel(); try { } finally { int count = _elementsContainer.Count; while (TakeDestroyAndRemoveElement()) { TurboContract.Assert(--count >= 0, conditionString: "--count >= 0"); } if (_elementsContainer.Count == 0) { _stoppedEvent.Set(); } } Profiling.Profiler.ObjectPoolDisposed(this.Name, false); } else { if (_elementsContainer.Count == 0) { _stoppedEvent.Set(); } } if (waitForRelease) { this.WaitUntilStop(); } }
/// <summary> /// Попробовать добавить элемент в очередь /// </summary> /// <param name="item">Элемент</param> /// <param name="localQueue">Локальная очередь (если есть)</param> /// <param name="forceGlobal">Обязательное добавление в глобальную очередь</param> /// <returns>Удалось ли добавить</returns> public bool TryAdd(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue, bool forceGlobal) { TurboContract.Requires(item != null, conditionString: "item != null"); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); bool result = false; try { } finally { if (!forceGlobal && localQueue != null && localQueue.TryAddLocal(item)) { result = true; } else { result = _globalQueue.TryAdd(item, 0); } } return(result); }
/// <summary> /// Удалить локальную очередь из массива /// </summary> /// <param name="localQueue">Локальная очередь</param> public void RemoveLocalQueue(ThreadPoolLocalQueue localQueue) { TurboContract.Requires(localQueue != null, conditionString: "localQueue != null"); TurboContract.Ensures(!_localQueues.Contains(localQueue)); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); lock (_syncObj) { var arrayCopy = _localQueues; TurboContract.Assert(arrayCopy != null, conditionString: "arrayCopy != null"); for (int i = 0; i < arrayCopy.Length; i++) { if (object.ReferenceEquals(Volatile.Read(ref arrayCopy[i]), localQueue)) { Volatile.Write(ref arrayCopy[i], null); return; } } } }
/// <summary> /// Сделать предложение по изменению числа потоков в IncreasingState /// </summary> /// <returns>Предложение</returns> private int MakeSuggestionInIncreasingState() { var curMeasure = GetCurrentMeasure(); var prevMeasure = GetPrevMeasure(); if (curMeasure.ThreadCount <= prevMeasure.ThreadCount) { GoToState("Thread count decreased externally", ExecutionThroughoutTrackerUpHardDownCorrectionState.FindBestDirection); return(ReturnSuggestion("Thread count decreased externally", 0)); } if (curMeasure.ThreadCount >= _maxThreadCount) { GoToState("Upper bound reached", ExecutionThroughoutTrackerUpHardDownCorrectionState.InOptimalState); return(ReturnSuggestion("Upper bound reached", 0)); } TurboContract.Assert(curMeasure.ThreadCount > prevMeasure.ThreadCount, conditionString: "curMeasure.ThreadCount > prevMeasure.ThreadCount"); double throughoutDiffCoef = EstimateThroughoutDiffCoef(prevMeasure.ThreadCount, prevMeasure.Throughout, curMeasure.ThreadCount, curMeasure.Throughout); double avgThroughoutDiffCoef = EstimateThroughoutDiffCoef(prevMeasure.ThreadCount, prevMeasure.AverageThroughout, curMeasure.ThreadCount, curMeasure.AverageThroughout); //Console.WriteLine("throughout diff = " + throughoutDiffCoef.ToString()); //Console.WriteLine("avgThroughout diff = " + avgThroughoutDiffCoef.ToString()); if (throughoutDiffCoef < IncreaseDirectionLocDropDiff && avgThroughoutDiffCoef < IncreaseDirectionAvgDropDiff) { GoToState("Throughout drop", ExecutionThroughoutTrackerUpHardDownCorrectionState.FindBestDirection); return(ReturnSuggestion("Throughout drop", 0)); } if (throughoutDiffCoef < IncreaseDirectionLocGoodDiff && avgThroughoutDiffCoef < IncreaseDirectionAvgGoodDiff) { GoToState("Throughout increase slightly", ExecutionThroughoutTrackerUpHardDownCorrectionState.InOptimalState); return(ReturnSuggestion("Throughout increase slightly", 0)); } return(ReturnSuggestion("Continue thread increase", 1)); }
/// <summary> /// Добавить элемент в массив /// </summary> /// <param name="element">Элемент</param> /// <returns>Индекс в массиве</returns> public int Add(T element) { TurboContract.Requires(element != null, conditionString: "element != null"); lock (_syncObj) { T[] data = _data; int index = -1; if (data.Length > _count) { for (int i = 0; i < data.Length; i++) { if (Volatile.Read(ref data[i]) == null) { index = i; break; } } } else { index = data.Length; data = IncreaseLength(); } TurboContract.Assert(index >= 0, conditionString: "index >= 0"); TurboContract.Assert(index < data.Length, conditionString: "index < data.Length"); TurboContract.Assert(data[index] == null, conditionString: "data[index] == null"); try { } finally { Volatile.Write(ref data[index], element); _count++; } return(index); } }
/// <summary> /// Сжать массив. Элементы двигать запрещено. /// </summary> private void CompactCore() { T[] data = _data; int count = _count; if (data.Length - count < CompactionOverhead || data.Length <= BlockSize) { return; } int emptyBackCount = 0; for (int i = data.Length - 1; i >= 0; i--) { if (Volatile.Read(ref data[i]) != null) { break; } emptyBackCount++; } if (emptyBackCount < CompactionOverhead) { return; } int copyCount = data.Length - emptyBackCount; int newSize = copyCount + (BlockSize - (copyCount % BlockSize)); TurboContract.Assert(newSize < data.Length, conditionString: "newSize < data.Length"); T[] newData = new T[newSize]; for (int i = 0; i < newData.Length; i++) { newData[i] = Volatile.Read(ref data[i]); } _data = newData; }
/// <summary> /// Writes single item to disk /// </summary> /// <param name="item">Item</param> private void SaveSingleItemToDisk(T item) { lock (_writeLock) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().Name); } RegionBinaryWriter writer = GetMemoryWriteStream(1); TurboContract.Assert(writer.BaseStream.Length == 0, conditionString: "writer.BaseStream.Length == 0"); TurboContract.Assert(writer.BaseStream.InnerStream.Length == 0, conditionString: "writer.BaseStream.InnerStream.Length == 0"); SerializeItemToStream(item, writer); // Write all data to disk writer.BaseStream.InnerStream.WriteTo(_writeStream); _writeStream.Flush(flushToDisk: false); ReleaseMemoryWriteStream(writer); } }
/// <summary> /// Moves head to the next non-completed segment /// </summary> /// <returns>New head segment</returns> private DiskQueueSegmentWrapper <T> MoveHeadToNonCompletedSegment() { TurboContract.Assert(Monitor.IsEntered(_segmentOperationsLock), conditionString: "Monitor.IsEntered(_segmentOperationsLock)"); DiskQueueSegmentWrapper <T> curHeadSegment = _headSegment; if (curHeadSegment.NextSegment == null || !curHeadSegment.IsCompleted) { return(curHeadSegment); } curHeadSegment = curHeadSegment.NextSegment; while (curHeadSegment.NextSegment != null && curHeadSegment.IsCompleted) { curHeadSegment = curHeadSegment.NextSegment; } _headSegment = curHeadSegment; VerifyConsistency(); return(curHeadSegment); }
private void VerifyConsistency() { TurboContract.Assert(Monitor.IsEntered(_segmentOperationsLock), "segment lock is not acquired"); TurboContract.Assert(_headSegment != null, conditionString: "_headSegment != null"); TurboContract.Assert(_tailSegment != null, conditionString: "_tailSegment != null"); TurboContract.Assert(_segments.Count > 0, conditionString: "_segments.Count > 0"); TurboContract.Assert(_tailSegment == _segments[_segments.Count - 1], conditionString: "_tailSegment == _segments[_segments.Count - 1]"); bool beforeHead = true; DiskQueueSegmentWrapper <T> prevSegment = null; _segments.ForEach(curSegment => { if (prevSegment != null) { TurboContract.Assert(prevSegment.NextSegment == curSegment, "Linked-list of segments is broken"); } if (curSegment == _headSegment) { TurboContract.Assert(beforeHead, "Head segments met twice"); beforeHead = false; } if (beforeHead) { TurboContract.Assert(curSegment.IsCompleted, "All segements before head should be in IsCompleted state"); } if (curSegment != _tailSegment) { TurboContract.Assert(curSegment.IsFull, "All segements before tail should be in IsFull state"); } prevSegment = curSegment; }); TurboContract.Assert(!beforeHead, "HeadSegment is not found in the list of segments"); }
/// <summary> /// Creates a new segment. /// Attention: waiters notification is required after the segment allocation (<see cref="_addMonitor"/>) /// </summary> /// <returns>Created segment</returns> private DiskQueueSegmentWrapper <T> AllocateNewSegment() { CheckDisposed(); TurboContract.Assert(Monitor.IsEntered(_segmentOperationsLock), conditionString: "Monitor.IsEntered(_segmentOperationsLock)"); TurboContract.Assert(!Monitor.IsEntered(_takeMonitor), conditionString: "!Monitor.IsEntered(_takeMonitor)"); TurboContract.Assert(!Monitor.IsEntered(_peekMonitor), conditionString: "!Monitor.IsEntered(_peekMonitor)"); var result = _segmentFactory.CreateSegmentWrapped(_segmentsPath, checked (++_lastSegmentNumber)); if (result == null) { throw new InvalidOperationException("CreateSegment returned null"); } TurboContract.Assert(result.Number == _lastSegmentNumber, conditionString: "result.Number == _lastSegmentNumber"); _segments.Add(result); _tailSegment.NextSegment = result; _tailSegment = result; VerifyConsistency(); return(result); }
/// <summary> /// Blocks background transferer and attempts to peek the item /// </summary> private bool TryPeekExclusively(out T item, TimeoutTracker timeoutTracker, CancellationToken token) { TurboContract.Assert(_isBackgroundTransferingEnabled, conditionString: "_isBackgroundTransferingEnabled"); using (var gateGuard = _backgoundTransfererExclusive.EnterMain(Timeout.Infinite, token)) // This should happen fast { TurboContract.Assert(gateGuard.IsAcquired, conditionString: "gateGuard.IsAcquired"); if (_peekMonitor.WaiterCount == 0) { if (TryPeekFast(out item)) { return(true); } if (timeoutTracker.OriginalTimeout == 0) { return(false); } } return(TryPeekSlow(out item, timeoutTracker, token)); } }
/// <summary> /// Освобождение ресурсов /// </summary> /// <param name="isUserCall">Вызвано ли пользователем</param> private void Dispose(bool isUserCall) { if (!_isDisposed) { _isDisposed = true; TurboContract.Assert(isUserCall, "Finalizer called for ThreadPoolGlobals. It should be disposed explicitly by calling Dispose on ThreadPool. ThreadPoolName: " + this.OwnerPoolName); if (isUserCall) { var perThreadData = _perThreadData.Values.ToArray(); TurboContract.Assert(perThreadData.All(o => o == null), "ThreadPoolGlobals contains thread information on Dispose"); if (perThreadData.Any(o => o != null)) { throw new InvalidOperationException("ThreadPoolGlobals contains thread information on Dispose"); } _perThreadData.Dispose(); _queues.Dispose(); } } }
/// <summary> /// Returns the item at the head of the queue without removing it (core method) /// </summary> /// <param name="item">The item at the head of the queue</param> /// <param name="timeout">Peeking timeout</param> /// <param name="token">Cancellation token</param> /// <returns>True if the item was read</returns> protected override bool TryPeekCore(out T item, int timeout, CancellationToken token) { if (_isDisposed) { throw new ObjectDisposedException(this.GetType().Name); } if (token.IsCancellationRequested) { throw new OperationCanceledException(token); } if (_peekMonitor.WaiterCount == 0) // Preserve fairness { var headSegment = _headSegment; TurboContract.Assert(headSegment != null, conditionString: "headSegment != null"); if (headSegment.TryPeek(out item)) { return(true); } } return(TryPeekSlow(out item, timeout, token)); }
/// <summary> /// Обновление состояния /// </summary> private void UpdateStateCore() { int timestamp = GetTimestamp(); int lastTestTime = Volatile.Read(ref _lastTestTime); if (Interlocked.CompareExchange(ref _lastTestTime, timestamp, lastTestTime) != lastTestTime) { return; } int minFreeElementsCount = Interlocked.Exchange(ref _minFreeElementsCount, int.MaxValue); TurboContract.Assert(minFreeElementsCount >= 0, conditionString: "minFreeElementsCount >= 0"); if (minFreeElementsCount == int.MaxValue) { Interlocked.Exchange(ref _elementToDestroy, 0); } else { Interlocked.Exchange(ref _elementToDestroy, minFreeElementsCount); } }
/// <summary> /// Выполнить переход в состояние /// </summary> /// <param name="description">Описание причин перехода</param> /// <param name="state">Новое состояние</param> private void GoToState(string description, ExecutionThroughoutTrackerUpHardDownCorrectionState state) { if (!CanChangeState(_state, state)) { throw new InvalidOperationException("Invalid state change from " + _state.ToString() + " to " + state.ToString()); } //Console.WriteLine(description + ". State = " + _state.ToString() + ", NewState = " + state.ToString()); if (_state != state) { _state = state; _enterStateTimeStamp = GetTimestamp(); _enterStateThroughoutData = this.GetCurrentMeasure(); _stateMeasureCount = 0; _findBestDirectionBlinkCount = 0; _optimalStateAverageThroughout = -1; TurboContract.Assert(_isPerfMeasureThreadWork == false, conditionString: "_isPerfMeasureThreadWork == false"); } }
/// <summary> /// Attempts to create the next BatchingQueueSegment in the Linked List structure /// </summary> /// <returns>true - segments created and can be read through <see cref="Next"/> property, false - no new segment created due to already created next segment</returns> internal bool Grow() { int reservedIndexWithFinalizationMark = _reservedIndexWithFinalizationMark; if (IsSegmentFinalized(reservedIndexWithFinalizationMark)) { return(false); } bool result = false; var newSegment = _preallocatedNext ?? new BatchingQueueSegment <T>(Capacity, unchecked (_batchId + 1)); SpinWait sw = new SpinWait(); try { } finally { reservedIndexWithFinalizationMark = _reservedIndexWithFinalizationMark; while (!IsSegmentFinalized(reservedIndexWithFinalizationMark)) { if (Interlocked.CompareExchange(ref _reservedIndexWithFinalizationMark, SetSegmentFinalized(reservedIndexWithFinalizationMark), reservedIndexWithFinalizationMark) == reservedIndexWithFinalizationMark) { result = Interlocked.CompareExchange(ref _next, newSegment, null) == null; TurboContract.Assert(result, "New segment update failed"); break; } sw.SpinOnceNoSleep(); reservedIndexWithFinalizationMark = _reservedIndexWithFinalizationMark; } } if (result && Capacity >= SegmentPreallocationCapacityThreshold) { newSegment.PreallocateNextSegment(); } return(result); }
/// <summary> /// Blocks the current thread until the next notification /// </summary> /// <param name="timeout">Tiemout in milliseconds</param> /// <returns>True if the current thread successfully received a notification</returns> /// <exception cref="SynchronizationLockException">externalLock is not acquired or acquired recursively</exception> /// <exception cref="ObjectDisposedException">ConditionVariable was disposed</exception> /// <exception cref="OperationInterruptedException">Waiting was interrupted by Dispose</exception> internal bool Wait(int timeout) { if (_isDisposed) { throw new ObjectDisposedException(nameof(MonitorObject), $"MonitorObject '{Name}' was disposed"); } TurboContract.Assert(Monitor.IsEntered(this), "External lock should be acquired"); if (timeout < -1) { timeout = Timeout.Infinite; } try { Interlocked.Increment(ref _waiterCount); // Waiting for signal if (!Monitor.Wait(this, timeout)) { return(false); } if (_isDisposed) { throw new OperationInterruptedException("Wait was interrupted by Dispose", new ObjectDisposedException(nameof(MonitorObject), $"MonitorObject '{Name}' was disposed")); } } finally { Interlocked.Decrement(ref _waiterCount); } return(true); }