IEnumerable <PostprocessedMessage> MessagesEnumerator() { tracer.Info("Enumerator entered"); var readerAndProcessorCallback = new Callback(this); ISequentialMediaReaderAndProcessor <PieceOfWork> readerAndProcessor; if (!useMockThreading) { readerAndProcessor = new SequentialMediaReaderAndProcessor <PieceOfWork, PieceOfWork, ThreadLocalData>(readerAndProcessorCallback, currentParams.Cancellation); } else { var mockedReaderAndProcessorImpl = new SequentialMediaReaderAndProcessorMock <PieceOfWork, PieceOfWork, ThreadLocalData>(readerAndProcessorCallback); mockedReaderAndProcessor = mockedReaderAndProcessorImpl; readerAndProcessor = mockedReaderAndProcessorImpl; } using (readerAndProcessor) { for (; ;) { currentParams.Cancellation.ThrowIfCancellationRequested(); PieceOfWork currentPieceOfWork = readerAndProcessor.ReadAndProcessNextPieceOfData(); if (currentPieceOfWork == null) { break; } currentPieceOfWork.perfop.Milestone("Starting consuming"); tracer.Info("Messages in output buffer: {0}", currentPieceOfWork.outputBuffer.Count); // Here is tricky: returning bytes buffer of the piece of work that was handled previously. // Bytes buffer of current piece (currentPieceOfWork.streamData) can still be used // by a thread processing the piece following the current one. if (currentParams.Direction == MessagesParserDirection.Forward) { SafeReturnStreamDataToThePool(currentPieceOfWork.prevStreamData); } else { SafeReturnStreamDataToThePool(currentPieceOfWork.nextStreamData); } foreach (var m in currentPieceOfWork.outputBuffer) { yield return(m); } var tmp = Interlocked.Decrement(ref peicesOfWorkBeingProgressed); tracer.Info("Finished consuming piece of work #{0} ({1} are still being processed)", currentPieceOfWork.id, tmp); ReturnOutputBufferToThePool(currentPieceOfWork.outputBuffer); } } tracer.Info("Enumerator exited"); }
public void ClientStopsReadingInTheMiddleOfSenquence() { FakeCallback callback = new FakeCallback(20, TimeSpan.FromMilliseconds(20), TimeSpan.FromMilliseconds(100)); var reader = new SequentialMediaReaderAndProcessor <object, object, object>(callback, CancellationToken.None); for (int i = 0; i < callback.ItemsCount / 2; ++i) { object obj = reader.ReadAndProcessNextPieceOfData(); Assert.AreEqual(FakeCallback.ItemIdxToData(i), (int)obj); FakeCallback.DoFakeJob(TimeSpan.FromMilliseconds(20)); } }
public void ProcessingIsMoreExpensiveThanReading_NanosecondsLevel() { FakeCallback callback = new FakeCallback(100000, TimeSpan.FromTicks(30), TimeSpan.FromTicks(100)); var reader = new SequentialMediaReaderAndProcessor <object, object, object>(callback, CancellationToken.None); for (int i = 0; i < callback.ItemsCount; ++i) { object obj = reader.ReadAndProcessNextPieceOfData(); Assert.AreEqual(FakeCallback.ItemIdxToData(i), (int)obj); FakeCallback.DoFakeJob(TimeSpan.FromTicks(8)); } }
public void ProcessingIsLessExpensiveThanReading() { FakeCallback callback = new FakeCallback(20, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(20)); var reader = new SequentialMediaReaderAndProcessor <object, object, object>(callback); for (int i = 0; i < callback.ItemsCount; ++i) { object obj = reader.ReadAndProcessNextPieceOfData(); Assert.AreEqual(FakeCallback.ItemIdxToData(i), (int)obj); FakeCallback.DoFakeJob(TimeSpan.FromMilliseconds(20)); } }
public void NullIsReturnedWhenEOFReached_CorrectValueOtherwise() { FakeCallback callback = new FakeCallback(50, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(20)); var reader = new SequentialMediaReaderAndProcessor <object, object, object>(callback, CancellationToken.None); for (int i = 0;; ++i) { object obj = reader.ReadAndProcessNextPieceOfData(); if (i == callback.ItemsCount) { Assert.IsNull(obj); } else { Assert.AreEqual(FakeCallback.ItemIdxToData(i), (int)obj); } if (obj == null) { break; } } }