/// <summary> /// It is ok to have another thread rerun this method after a halt(). /// </summary> public void Run() { if (Interlocked.Exchange(ref _running, 1) != 0) { throw new InvalidOperationException("Thread is already running"); } _sequenceBarrier.ClearAlert(); NotifyStart(); T evt = null; var nextSequence = _sequence.Value + 1L; try { while (true) { try { var availableSequence = _sequenceBarrier.WaitFor(nextSequence); if (_batchStartAware != null) { _batchStartAware.OnBatchStart(availableSequence - nextSequence + 1); } while (nextSequence <= availableSequence) { evt = _dataProvider[nextSequence]; _eventHandler.OnEvent(evt, nextSequence, nextSequence == availableSequence); nextSequence++; } _sequence.SetValue(availableSequence); } catch (TimeoutException) { NotifyTimeout(_sequence.Value); } catch (AlertException) { if (_running == 0) { break; } } catch (Exception ex) { _exceptionHandler.HandleEventException(ex, nextSequence, evt); _sequence.SetValue(nextSequence); nextSequence++; } } } finally { NotifyShutdown(); _running = 0; } }
/// <summary> /// Start the worker pool processing events in sequence. /// </summary> /// <exception cref="InvalidOperationException">if the pool is already started or halted</exception> public RingBuffer <T> Start(TaskScheduler taskScheduler) { var previousRunState = Interlocked.CompareExchange(ref _runState, ProcessorRunStates.Running, ProcessorRunStates.Idle); if (previousRunState == ProcessorRunStates.Running) { throw new InvalidOperationException("WorkerPool is already running"); } if (previousRunState == ProcessorRunStates.Halted) { throw new InvalidOperationException("WorkerPool is halted and cannot be restarted"); } var cursor = _ringBuffer.Cursor; _workSequence.SetValue(cursor); foreach (var workProcessor in _workProcessors) { workProcessor.Sequence.SetValue(cursor); workProcessor.Start(taskScheduler); } return(_ringBuffer); }
public void Publish(long sequence) { _cursor.SetValue(sequence); if (_isBlockingWaitStrategy) { _waitStrategy.SignalAllWhenBlocking(); } }
private bool HasAvailableCapacity(ISequence[] gatingSequences, int requiredCapacity, long cursorValue) { var wrapPoint = (cursorValue + requiredCapacity) - _bufferSize; var cachedGatingSequence = _gatingSequenceCache.Value; if (wrapPoint > cachedGatingSequence || cachedGatingSequence > cursorValue) { long minSequence = Util.GetMinimumSequence(gatingSequences, cursorValue); _gatingSequenceCache.SetValue(minSequence); if (wrapPoint > minSequence) { return(false); } } return(true); }
private bool HasAvailableCapacity(int requiredCapacity, long cursorValue) { var wrapPoint = (cursorValue + requiredCapacity) - _bufferSize; var cachedGatingSequence = _gatingSequenceCache.Value; if (wrapPoint > cachedGatingSequence || cachedGatingSequence > cursorValue) { var minSequence = DisruptorUtil.GetMinimumSequence(Volatile.Read(ref _gatingSequences), cursorValue); _gatingSequenceCache.SetValue(minSequence); if (wrapPoint > minSequence) { return(false); } } return(true); }
/// <summary> /// Start the worker pool processing events in sequence. /// </summary> /// <returns>the <see cref="RingBuffer{T}"/> used for the work queue.</returns> /// <exception cref="InvalidOperationException">if the pool has already been started and not halted yet</exception> public RingBuffer <T> Start(IExecutor executor) { if (Interlocked.Exchange(ref _running, 1) != 0) { throw new InvalidOperationException("WorkerPool has already been started and cannot be restarted until halted"); } var cursor = _ringBuffer.Cursor; _workSequence.SetValue(cursor); foreach (var workProcessor in _workProcessors) { workProcessor.Sequence.SetValue(cursor); executor.Execute(workProcessor.Run); } return(_ringBuffer); }
private void ProcessEvents() { var nextSequence = _sequence.Value + 1L; while (true) { try { var availableSequence = _sequenceBarrier.WaitFor(nextSequence); _batchStartAware.OnBatchStart(availableSequence - nextSequence + 1); while (nextSequence <= availableSequence) { ref T evt = ref _dataProvider[nextSequence]; _eventHandler.OnEvent(ref evt, nextSequence, nextSequence == availableSequence); nextSequence++; } _sequence.SetValue(availableSequence); }
public void Claim(long sequence) { _cursor.SetValue(sequence); }