public void ShouldCallMethodsInLifecycleOrder() { using (_mocks.Ordered()) { Expect.Call(() => batchHandler.OnAvailable(ringBuffer.GetEntry(0))); Expect.Call(() => batchHandler.OnEndOfBatch()).WhenCalled(m => _latch.Set()); Expect.Call(() => batchHandler.OnCompletion()); } _mocks.ReplayAll(); Thread thread = new Thread(batchConsumer.Run); thread.Start(); Assert.AreEqual(-1L, batchConsumer.Sequence); producerBarrier.Commit(producerBarrier.NextEntry()); Assert.IsTrue(_latch.WaitOne(TimeSpan.FromSeconds(1))); batchConsumer.Halt(); thread.Join(); _mocks.VerifyAll(); }
/// <summary> /// It is ok to have another thread rerun this method after a halt(). /// </summary> public void Run() { _running.Data = true; OnStart(); var nextSequence = Sequence + 1; while (_running.Data) { var waitForResult = _consumerBarrier.WaitFor(nextSequence); if (!waitForResult.IsAlerted) { var availableSequence = waitForResult.AvailableSequence; while (nextSequence <= availableSequence) { T data = _consumerBarrier.GetEntry(nextSequence); _handler.OnAvailable(nextSequence, data); nextSequence++; } _handler.OnEndOfBatch(); if (_delaySequenceWrite) { if (nextSequence > _nextSequencePublish) { Sequence = nextSequence - 1; // volatile write _nextSequencePublish += _sequenceUpdatePeriod; } } else { Sequence = nextSequence - 1; // volatile write } } } OnStop(); }