public void ShouldNotReturnNextClaimSequenceUntilBufferHasReserve() { var dependentSequence = new Sequence(Sequencer.InitialCursorValue); Sequence[] dependentSequences = { dependentSequence }; _claimStrategy.SetSequence(_claimStrategy.BufferSize - 1L, dependentSequences); var done = new Volatile4.Boolean(false); var beforeLatch = new ManualResetEvent(false); var afterLatch = new ManualResetEvent(false); new Thread( () => { beforeLatch.Set(); Assert.AreEqual(_claimStrategy.BufferSize, _claimStrategy.IncrementAndGet(dependentSequences)); done.WriteFullFence(true); afterLatch.Set(); }).Start(); beforeLatch.WaitOne(); Thread.Sleep(100); Assert.IsFalse(done.ReadFullFence()); dependentSequence.Value = (dependentSequence.Value + 1L); afterLatch.WaitOne(); Assert.AreEqual(_claimStrategy.BufferSize, _claimStrategy.Sequence); }
private void CheckNotStarted() { if (_running.ReadFullFence()) { throw new InvalidOperationException("All event handlers must be added before calling starts."); } }
/// <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); }
public void ShouldNotReturnNextClaimSequenceUntilBufferHasReserve() { var dependentSequence = new Sequence(Sequencer.InitialCursorValue); var dependentSequences = new[] { dependentSequence }; _claimStrategy.SetSequence(BufferSize - 1L, dependentSequences); var done = new Volatile4.Boolean(false); var beforeLatch = new ManualResetEvent(false); var afterLatch = new ManualResetEvent(false); new Thread(() => { beforeLatch.Set(); Assert.AreEqual(_claimStrategy.BufferSize, _claimStrategy.IncrementAndGet(dependentSequences)); done.WriteFullFence(true); afterLatch.Set(); }).Start(); beforeLatch.WaitOne(); Thread.Sleep(1000); Assert.IsFalse(done.ReadFullFence()); dependentSequence.Value = dependentSequence.Value + 1L; afterLatch.WaitOne(); Assert.AreEqual(_claimStrategy.BufferSize, _claimStrategy.Sequence); }
public void ReadFullFenceReturnsInitialValue() { Assert.AreEqual(InitialValue, _volatile.ReadFullFence()); }