/// <summary>
        /// Захватить лучший элемент из доступных
        /// </summary>
        /// <param name="element">Захваченный элемент</param>
        /// <returns>Удалось ли захватить</returns>
        private bool TryTakeBest(out PoolElementWrapper <T> element)
        {
            TurboContract.Ensures((TurboContract.Result <bool>() == false && TurboContract.ValueAtReturn(out element) == null) ||
                                  (TurboContract.Result <bool>() == true && TurboContract.ValueAtReturn(out element) != null && TurboContract.ValueAtReturn(out element).IsBusy));

            PoolElementWrapper <T> b1, b2, b3;
            PoolElementWrapper <T> earlyStopResult = FindBest3WithStopping(out b1, out b2, out b3);

            if (earlyStopResult != null)
            {
                TurboContract.Assert(earlyStopResult.IsBusy, conditionString: "earlyStopResult.IsBusy");
                element = earlyStopResult;
                return(true);
            }
            if (b1 != null && b1.TryMakeBusyAtomic() && !b1.IsRemoved)
            {
                element = b1;
                return(true);
            }
            if (b2 != null && b2.TryMakeBusyAtomic() && !b2.IsRemoved)
            {
                element = b2;
                return(true);
            }
            if (b3 != null && b3.TryMakeBusyAtomic() && !b3.IsRemoved)
            {
                element = b3;
                return(true);
            }

            element = null;
            return(false);
        }
        /// <summary>
        /// Выборка элемента из головы (может вызываться из любого потока)
        /// </summary>
        /// <param name="item">Выбранный элемент</param>
        /// <returns>Удалось ли сделать выборку</returns>
        public bool TrySteal(out ThreadPoolWorkItem item)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);

            if (HasElements(_head, _tail))
            {
                lock (_syncObj)
                {
                    int head = _head;
                    if (HasElements(head, _tail))
                    {
                        item = Interlocked.Exchange(ref _data[head % QueueSize], null);
                        if (item != null)
                        {
                            //RemoveElementFromHead();
                            _head = head + 1;
                            return(true);
                        }
                    }
                }
            }

            item = null;
            return(false);
        }
        /// <summary>Code contracts</summary>
        public bool TryGetAssociation(T key, out LifetimeBase val)
        {
            TurboContract.Ensures((TurboContract.Result <bool>() == true && TurboContract.ValueAtReturn <LifetimeBase>(out val) != null) ||
                                  (TurboContract.Result <bool>() == false && TurboContract.ValueAtReturn <LifetimeBase>(out val) == null));

            throw new NotImplementedException();
        }
        // =====================


        /// <summary>
        /// Попробовать выполнить похищение элемента из соседних локальных очередей
        /// </summary>
        /// <param name="localQueue">Локальная очередь текущего потока</param>
        /// <param name="otherLocalQueues">Разреженный массив локальных очередей других потоков</param>
        /// <param name="item">Выбранный элемент</param>
        /// <returns>Удалось ли сделать выборку</returns>
        private bool TryTakeFromOtherLocalQueues(ThreadPoolLocalQueue localQueue, ThreadPoolLocalQueue[] otherLocalQueues, out ThreadPoolWorkItem item)
        {
            TurboContract.Requires(otherLocalQueues != null, conditionString: "otherLocalQueues != null");
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);


            bool result = false;

            item = null;

            try { }
            finally
            {
                int length = otherLocalQueues.Length;
                int index  = Interlocked.Increment(ref _stealIndex) & int.MaxValue;
                for (int i = 0; i < length; i++, index++)
                {
                    var otherQueue = Volatile.Read(ref otherLocalQueues[index % length]);
                    if (otherQueue != null && otherQueue != localQueue && otherQueue.TrySteal(out item))
                    {
                        result = true;
                        break;
                    }
                }
            }

            return(result);
        }
        protected override bool TryGetAssociationInner(T key, out LifetimeBase val)
        {
            TurboContract.Requires(key != null, conditionString: "key != null");
            TurboContract.Ensures((TurboContract.Result <bool>() == true && TurboContract.ValueAtReturn <LifetimeBase>(out val) != null) ||
                                  (TurboContract.Result <bool>() == false && TurboContract.ValueAtReturn <LifetimeBase>(out val) == null));

            throw new NotImplementedException();
        }
        public bool TryTakeItem(ThreadPoolThreadLocals local, bool doLocalSearch, bool doWorkSteal, out ThreadPoolWorkItem item, int timeout, CancellationToken token, bool throwOnCancellation)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);
            TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed");

            if (local != null)
            {
                return(_queues.TryTake(local.LocalQueue, doLocalSearch, doWorkSteal, out item, timeout, token, throwOnCancellation));
            }
            else
            {
                return(_queues.TryTake(null, doLocalSearch, doWorkSteal, out item, timeout, token, throwOnCancellation));
            }
        }
        public bool TryTakeItem(ThreadPoolThreadLocals local, out ThreadPoolWorkItem item)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);
            TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed");

            if (local != null)
            {
                return(_queues.TryTake(local.LocalQueue, out item, 0, new CancellationToken(), true));
            }
            else
            {
                return(_queues.TryTake(null, out item, 0, new CancellationToken(), true));
            }
        }
Exemple #8
0
        /// <summary>
        /// Попробовать достать элемент из очереди
        /// </summary>
        /// <param name="item">Выбранный элемент</param>
        /// <returns>Удалось ли выбрать</returns>
        public bool TryTake(out ThreadPoolWorkItem item)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);

            while (this.HasElements())
            {
                Segment head = _head;
                if (head.TryTake(out item))
                {
                    return(true);
                }
            }
            item = null;
            return(false);
        }
        /// <summary>
        /// Выборка элемента из хвоста (должно вызываться из потока-владельца)
        /// </summary>
        /// <param name="item">Выбранный элемент</param>
        /// <returns>Удалось ли сделать выборку</returns>
        public bool TryTakeLocal(out ThreadPoolWorkItem item)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);

            int tail = _tail;

            if (HasElements(_head, tail))
            {
                item = Interlocked.Exchange(ref _data[(tail - 1) % QueueSize], null);
                if (item != null)
                {
                    //RemoveElementFromTail();
                    _tail = tail - 1;
                    return(true);
                }
            }

            item = null;
            return(false);
        }
Exemple #10
0
            /// <summary>
            /// Попытаться выбрать элемент из сегмента
            /// </summary>
            /// <param name="item">Выбранный элемент</param>
            /// <returns>Удалось ли сделать выборку</returns>
            public bool TryTake(out ThreadPoolWorkItem item)
            {
                TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);

                SpinWait sw   = new SpinWait();
                int      head = _head;

                while (HasElements(head, _tail))
                {
                    if (Interlocked.CompareExchange(ref _head, head + 1, head) == head)
                    {
                        SpinWait           itemSw    = new SpinWait();
                        ThreadPoolWorkItem localItem = null;
                        while ((localItem = Volatile.Read(ref _data[head])) == null)
                        {
                            itemSw.SpinOnce();
                        }
                        item = localItem;
                        Volatile.Write(ref _data[head], null);

                        if (head + 1 >= SegmentSize)
                        {
                            SpinWait headSw = new SpinWait();
                            while (_next == null)
                            {
                                headSw.SpinOnce();
                            }
                            _parent._head = _next;
                        }

                        return(true);
                    }

                    sw.SpinOnce();
                    head = _head;
                }

                item = null;
                return(false);
            }
Exemple #11
0
        /// <summary>
        /// Attempts to resolve the object held by the container.
        /// Resolution can fail when required injection objects not found
        /// </summary>
        /// <param name="resolver">Injection resolver to acquire parameters</param>
        /// <param name="val">Resolved instance of the object</param>
        /// <returns>True if the object was successfully resolved</returns>
        public bool TryGetInstance(IInjectionResolver resolver, out object val)
        {
            TurboContract.Requires(resolver != null, conditionString: "resolver != null");
            TurboContract.Ensures((TurboContract.Result <bool>() == true &&
                                   ((TurboContract.ValueAtReturn(out val) != null && TurboContract.ValueAtReturn(out val).GetType() == this.OutputType) ||
                                    (TurboContract.ValueAtReturn(out val) == null && this.OutputType.IsAssignableFromNull()))) ||
                                  (TurboContract.Result <bool>() == false && TurboContract.ValueAtReturn(out val) == null));


            try
            {
                val = GetInstance(resolver);
                return(true);
            }
            catch (CommonIoCException)
            {
            }
            catch (KeyNotFoundException)
            {
            }

            val = null;
            return(false);
        }
        /// <summary>
        /// Попытаться выбрать элемент
        /// </summary>
        /// <param name="localQueue">Локальная очередь (если есть)</param>
        /// <param name="doLocalSearch">Делать ли поиск в локальной очереди</param>
        /// <param name="doWorkSteal">Разрешено ли похищение работы</param>
        /// <param name="item">Выбранный элемент</param>
        /// <param name="timeout">Таймаут</param>
        /// <param name="token">Токен отмены</param>
        /// <param name="throwOnCancellation">Выбрасывать ли исключение при отмене по токену</param>
        /// <returns>Удалось ли выбрать</returns>
        public bool TryTake(ThreadPoolLocalQueue localQueue, bool doLocalSearch, bool doWorkSteal, out ThreadPoolWorkItem item, int timeout, CancellationToken token, bool throwOnCancellation)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);
            TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed");

            // Пробуем выбрать из локальной очереди
            if (doLocalSearch && localQueue != null)
            {
                bool taken = false;
                try { }
                finally
                {
                    taken = localQueue.TryTakeLocal(out item);
                }
                if (taken)
                {
                    return(true);
                }
            }

            // Если нельзя делать похищение, то сразу забираем из очереди
            if (!doWorkSteal)
            {
                return(_globalQueue.TryTake(out item, timeout, token, throwOnCancellation));
            }

            // Пытаемся выбрать из общей очереди (если не удаётся, то нужно проверить возможность похищения)
            if (_globalQueue.TryTake(out item, 0, new CancellationToken(), false))
            {
                return(true);
            }

            // Пытаемся похитить элемент
            if (TryTakeFromOtherLocalQueues(localQueue, _localQueues, out item))
            {
                return(true);
            }

            if (timeout == 0)
            {
                // Попытки не дали результатов => выходим
                item = null;
                return(false);
            }

            // Если не нужно просыпаться для похищения, то просто выбриаем из общей очереди
            if (_stealAwakePeriod <= 0)
            {
                return(_globalQueue.TryTake(out item, timeout, token, throwOnCancellation));
            }


            if (timeout < 0)
            {
                // Если таймаут не ограничен, то выбираем из основной осереди и периодически пытаемся похитить
                while (true)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    if (_globalQueue.TryTake(out item, _stealAwakePeriod, token, throwOnCancellation))
                    {
                        return(true);
                    }

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    if (TryTakeFromOtherLocalQueues(localQueue, _localQueues, out item))
                    {
                        return(true);
                    }
                }
            }
            else
            {
                // Делаем замеры таймаута
                uint startTime = GetTimestamp();
                int  restTime  = timeout;

                while (restTime > 0)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    if (_globalQueue.TryTake(out item, Math.Min(_stealAwakePeriod, restTime), token, throwOnCancellation))
                    {
                        return(true);
                    }

                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    if (TryTakeFromOtherLocalQueues(localQueue, _localQueues, out item))
                    {
                        return(true);
                    }

                    restTime = UpdateTimeout(startTime, timeout);
                }
            }

            if (token.IsCancellationRequested && throwOnCancellation)
            {
                throw new OperationCanceledException(token);
            }

            item = null;
            return(false);
        }
        public bool TryResolve(T key, out object val)
        {
            TurboContract.Requires(key != null, conditionString: "key != null");
            TurboContract.Ensures(TurboContract.Result <bool>() == true || (TurboContract.Result <bool>() == false && TurboContract.ValueAtReturn <object>(out val) == null));

            throw new NotImplementedException();
        }
        /// <summary>
        /// Попытаться получить элемент из главной очереди
        /// </summary>
        /// <param name="item">Полученный элемент</param>
        /// <param name="timeout">Таймаут</param>
        /// <param name="token">Токен отмены</param>
        /// <param name="throwOnCancellation">Выбрасывать ли исключение при отмене по токену</param>
        /// <returns>Удалось ли получить</returns>
        public bool TryTake(out ThreadPoolWorkItem item, int timeout, CancellationToken token, bool throwOnCancellation)
        {
            TurboContract.Ensures(TurboContract.Result <bool>() == false || TurboContract.ValueAtReturn(out item) != null);

            item = null;

            if (token.IsCancellationRequested)
            {
                if (throwOnCancellation)
                {
                    throw new OperationCanceledException(token);
                }

                return(false);
            }

            bool occupiedNodesExist = _occupiedNodes.Wait(0);

            if (occupiedNodesExist == false && timeout != 0)
            {
                occupiedNodesExist = _occupiedNodes.Wait(timeout, token, throwOnCancellation);
            }

            if (occupiedNodesExist)
            {
                bool wasElementTaken = false;
                bool takePerformed   = true;
                try
                {
                    if (token.IsCancellationRequested)
                    {
                        if (throwOnCancellation)
                        {
                            throw new OperationCanceledException(token);
                        }

                        return(false);
                    }
                    wasElementTaken = _mainQueue.TryTake(out item);
                    takePerformed   = false;
                    TurboContract.Assert(wasElementTaken, "Incorrect collection state. Can't take items from collection when they should be there");
                }
                finally
                {
                    if (wasElementTaken)
                    {
                        if (_freeNodes != null)
                        {
                            // Не освобождаем, если запрошен экстеншн
                            if (Volatile.Read(ref _extendedCapacityRequest) <= 0 || Interlocked.Decrement(ref _extendedCapacityRequest) < 0)
                            {
                                _freeNodes.Release();
                            }
                        }
                    }
                    else
                    {
                        if (takePerformed)
                        {
                            _occupiedNodes.Release();
                        }
                    }
                }
            }
            return(occupiedNodesExist);
        }