Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 4
0
        /// <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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        /// <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();
                    }
                }
            }
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
0
        /// <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);
        }
Ejemplo n.º 10
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);
        }
Ejemplo n.º 11
0
        /// <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");
                }
            }
        }
Ejemplo n.º 14
0
        /// <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));
        }
Ejemplo n.º 18
0
        /// <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);
            }
        }
Ejemplo n.º 19
0
        /// <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);
            }
        }
Ejemplo n.º 21
0
        /// <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);
        }
Ejemplo n.º 22
0
        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");
        }
Ejemplo n.º 23
0
        /// <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);
        }
Ejemplo n.º 24
0
        /// <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));
            }
        }
Ejemplo n.º 25
0
        /// <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();
                }
            }
        }
Ejemplo n.º 26
0
        /// <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));
        }
Ejemplo n.º 27
0
        /// <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");
            }
        }
Ejemplo n.º 29
0
        /// <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);
        }
Ejemplo n.º 30
0
        /// <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);
        }