/// <summary> /// Claim the next sequence in the <see cref="Sequencer"/> /// The caller should be held up until the claimed sequence is available by tracking the dependentSequences. /// </summary> /// <param name="dependentSequences">dependentSequences to be checked for range.</param> /// <returns>the index to be used for the publishing.</returns> public long IncrementAndGet(Sequence[] dependentSequences) { MutableLong minGatingSequence = _minGatingSequenceThreadLocal.Value; WaitForCapacity(dependentSequences, minGatingSequence); long nextSequence = _claimSequence.IncrementAndGet(); WaitForFreeSlotAt(nextSequence, dependentSequences, minGatingSequence); return(nextSequence); }
/// <summary> /// It is ok to have another thread re-run this method after a halt(). /// </summary> public void Run() { if (!_running.AtomicCompareExchange(Running, Stopped)) { throw new InvalidOperationException("Thread is already running"); } _sequenceBarrier.ClearAlert(); NotifyStart(); var processedSequence = true; long nextSequence = _sequence.Value; T eventRef = null; while (true) { try { if (processedSequence) { processedSequence = false; nextSequence = _workSequence.IncrementAndGet(); _sequence.Value = nextSequence - 1L; } _sequenceBarrier.WaitFor(nextSequence); eventRef = _ringBuffer[nextSequence]; _workHandler.OnEvent(eventRef); processedSequence = true; } catch (AlertException) { if (_running.ReadFullFence() == Stopped) { break; } } catch (Exception ex) { _exceptionHandler.HandleEventException(ex, nextSequence, eventRef); processedSequence = true; } } NotifyShutdown(); _running.WriteFullFence(Stopped); }