private void CheckOnlyStartedOnce() { if (!_running.AtomicCompareExchange(Running, Stopped)) { throw new InvalidOperationException("Disruptor.start() must only be called once."); } }
/// <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); }
/// <summary> /// It is ok to have another thread rerun this method after a halt(). /// </summary> public void Run() { if (!_running.AtomicCompareExchange(Running, Stopped)) { throw new InvalidOperationException("Thread is already running"); } _sequenceBarrier.ClearAlert(); NotifyStart(); T evt = null; long nextSequence = _sequence.Value + 1L; while (true) { try { long availableSequence = _sequenceBarrier.WaitFor(nextSequence); while (nextSequence <= availableSequence) { evt = _ringBuffer[nextSequence]; _eventHandler.OnNext(evt, nextSequence, nextSequence == availableSequence); nextSequence++; } _sequence.LazySet(nextSequence - 1L); } catch (AlertException) { if (!_running.ReadFullFence()) { break; } } catch (Exception ex) { _exceptionHandler.HandleEventException(ex, nextSequence, evt); _sequence.LazySet(nextSequence); nextSequence++; } } NotifyShutdown(); _running.WriteFullFence(Stopped); }
/// <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(TaskScheduler taskScheduler) { if (!_running.AtomicCompareExchange(Running, Stopped)) { throw new InvalidOperationException("WorkerPool has already been started and cannot be restarted until halted."); } long cursor = _ringBuffer.Cursor; _workSequence.Value = cursor; for (int i = 0; i < _workProcessors.Length; i++) { var workProcessor = _workProcessors[i]; workProcessor.Sequence.Value = cursor; Task.Factory.StartNew(workProcessor.Run, CancellationToken.None, TaskCreationOptions.None, taskScheduler); } return(_ringBuffer); }
public void AtomicCompareExchangeReturnsTrueIfComparandEqualsCurrentValue() { Assert.IsTrue(_volatile.AtomicCompareExchange(NewValue, InitialValue)); }