/// <summary> /// Добавить локальную оередь в массив /// </summary> /// <param name="localQueue">Локальная очередь потока</param> public void AddLocalQueue(ThreadPoolLocalQueue localQueue) { Contract.Requires(localQueue != null); Contract.Ensures(Contract.Exists(_localQueues, o => o == localQueue)); Debug.Assert(!_isDisposed); lock (_syncObj) { var arrayCopy = _localQueues; Debug.Assert(arrayCopy != null); for (int i = 0; i < arrayCopy.Length; i++) { Debug.Assert(Volatile.Read(ref arrayCopy[i]) != localQueue); if (Volatile.Read(ref arrayCopy[i]) == null) { Volatile.Write(ref arrayCopy[i], localQueue); return; } } int oldLength = arrayCopy.Length; Array.Resize(ref arrayCopy, oldLength + 4); Volatile.Write(ref arrayCopy[oldLength], localQueue); _localQueues = arrayCopy; } }
// ===================== /// <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); }
/// <summary> /// Добавить локальную оередь в массив /// </summary> /// <param name="localQueue">Локальная очередь потока</param> public void AddLocalQueue(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++) { TurboContract.Assert(Volatile.Read(ref arrayCopy[i]) != localQueue, conditionString: "Volatile.Read(ref arrayCopy[i]) != localQueue"); if (Volatile.Read(ref arrayCopy[i]) == null) { Volatile.Write(ref arrayCopy[i], localQueue); return; } } int oldLength = arrayCopy.Length; Array.Resize(ref arrayCopy, oldLength + 4); Volatile.Write(ref arrayCopy[oldLength], localQueue); _localQueues = arrayCopy; } }
public ThreadPoolWorkItem Take(ThreadPoolLocalQueue localQueue) { ThreadPoolWorkItem item = null; bool result = TryTake(localQueue, true, true, out item, -1, new CancellationToken(), true); TurboContract.Assert(result, "Something went wrong. Take not return any result."); return(item); }
public ThreadPoolWorkItem Take(ThreadPoolLocalQueue localQueue, CancellationToken token) { ThreadPoolWorkItem item = null; bool result = TryTake(localQueue, true, true, out item, -1, token, true); Debug.Assert(result, "Something went wrong. Take not return any result."); return(item); }
/// <summary> /// Конструктор ThreadPoolThreadLocals /// </summary> /// <param name="globals">Глобальные данные пула</param> /// <param name="createLocalQueue">Создавать ли локальную очередь</param> public ThreadPoolThreadLocals(ThreadPoolGlobals globals, bool createLocalQueue) { TurboContract.Requires(globals != null, conditionString: "globals != null"); Globals = globals; if (createLocalQueue) { LocalQueue = new ThreadPoolLocalQueue(); } _isDisposed = false; }
/// <summary> /// Конструктор ThreadPoolThreadLocals /// </summary> /// <param name="globals">Глобальные данные пула</param> /// <param name="createLocalQueue">Создавать ли локальную очередь</param> public ThreadPoolThreadLocals(ThreadPoolGlobals globals, bool createLocalQueue) { Contract.Requires(globals != null); Globals = globals; if (createLocalQueue) { LocalQueue = new ThreadPoolLocalQueue(); } _isDisposed = false; }
// ================ /// <summary> /// Переместить все элементы из локальной очереди в общую /// </summary> /// <param name="localQueue">Локальная очередь</param> public void MoveItemsFromLocalQueueToGlobal(ThreadPoolLocalQueue localQueue) { TurboContract.Requires(localQueue != null, conditionString: "localQueue != null"); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); try { } finally { ThreadPoolWorkItem item = null; while (localQueue.TrySteal(out item)) { _globalQueue.ForceAdd(item); } } }
public bool TryAddItem(ThreadPoolWorkItem item, bool forceGlobal) { Contract.Requires(item != null); Debug.Assert(!_isDisposed); ThreadPoolLocalQueue localQueue = null; if (!forceGlobal) { ThreadPoolThreadLocals threadLocal = _perThreadData.Value; localQueue = threadLocal != null ? threadLocal.LocalQueue : null; } return(_queues.TryAdd(item, localQueue, forceGlobal)); }
public bool TryAddItem(ThreadPoolWorkItem item, bool forceGlobal) { TurboContract.Requires(item != null, conditionString: "item != null"); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); ThreadPoolLocalQueue localQueue = null; if (!forceGlobal) { ThreadPoolThreadLocals threadLocal = _perThreadData.Value; localQueue = threadLocal != null ? threadLocal.LocalQueue : null; } return(_queues.TryAdd(item, localQueue, forceGlobal)); }
// ================ /// <summary> /// Переместить все элементы из локальной очереди в общую /// </summary> /// <param name="localQueue">Локальная очередь</param> public void MoveItemsFromLocalQueueToGlobal(ThreadPoolLocalQueue localQueue) { Contract.Requires(localQueue != null); Debug.Assert(!_isDisposed); try { } finally { ThreadPoolWorkItem item = null; while (localQueue.TrySteal(out item)) { _globalQueue.ForceAdd(item); } } }
/// <summary> /// Добавить элемент в очередь /// </summary> /// <param name="item">Элемент</param> /// <param name="localQueue">Локальная очередь (если есть)</param> /// <param name="forceGlobal">Обязательное добавление в глобальную очередь</param> public void Add(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue, bool forceGlobal) { Contract.Requires(item != null); Debug.Assert(!_isDisposed); try { } finally { if (forceGlobal || localQueue == null || !localQueue.TryAddLocal(item)) { bool addToMainRes = _globalQueue.TryAdd(item, -1); Debug.Assert(addToMainRes); } } }
/// <summary> /// Добавить элемент в очередь /// </summary> /// <param name="item">Элемент</param> /// <param name="localQueue">Локальная очередь (если есть)</param> /// <param name="forceGlobal">Обязательное добавление в глобальную очередь</param> public void Add(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue, bool forceGlobal) { TurboContract.Requires(item != null, conditionString: "item != null"); TurboContract.Assert(!_isDisposed, conditionString: "!_isDisposed"); try { } finally { if (forceGlobal || localQueue == null || !localQueue.TryAddLocal(item)) { bool addToMainRes = _globalQueue.TryAdd(item, -1); TurboContract.Assert(addToMainRes, conditionString: "addToMainRes"); } } }
// ====================== /// <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="localQueue">Локальная очередь</param> public void RemoveLocalQueue(ThreadPoolLocalQueue localQueue) { Contract.Requires(localQueue != null); Contract.Ensures(!Contract.Exists(_localQueues, o => o == localQueue)); Debug.Assert(!_isDisposed); lock (_syncObj) { var arrayCopy = _localQueues; Debug.Assert(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> /// Попробовать добавить элемент в очередь /// </summary> /// <param name="item">Элемент</param> /// <param name="localQueue">Локальная очередь (если есть)</param> /// <param name="forceGlobal">Обязательное добавление в глобальную очередь</param> /// <returns>Удалось ли добавить</returns> public bool TryAdd(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue, bool forceGlobal) { Contract.Requires(item != null); Debug.Assert(!_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> /// Попробовать добавить элемент в очередь /// </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); }
public bool TryTake(ThreadPoolLocalQueue localQueue, out ThreadPoolWorkItem item, int timeout, CancellationToken token, bool throwOnCancellation) { return(TryTake(localQueue, true, true, out item, timeout, token, throwOnCancellation)); }
/// <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 void Add(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue) { this.Add(item, localQueue, false); }
public bool TryAdd(ThreadPoolWorkItem item, ThreadPoolLocalQueue localQueue) { return(this.TryAdd(item, localQueue, false)); }