public void Dispose_ExceptionInWorkerPropagates(int totThreads) { TaskCompletionSource <object> taskBlocker1 = new TaskCompletionSource <object>(); void DoMockWorkBlocking(MockWorkIn work, CancellationToken token) { taskBlocker1.Task.Wait(); throw new MockException(); } CancellationTokenSource ts = new CancellationTokenSource(); var cfg = new MultiThreadedWorkerConfig(totThreads); MultiThreadedWorker <MockWorkIn> mtw = new MultiThreadedWorker <MockWorkIn>(cfg, DoMockWorkBlocking); mtw.AddWorkItem(new MockWorkIn(1), ts.Token); TestDelegate disposeDel = delegate() { try { taskBlocker1.SetResult(null); mtw.Dispose(); } catch (AggregateException ex) { throw ex.InnerException; } }; Assert.Throws <MockException>(disposeDel); }
public void Dispose_CancelsPendingTasks(int totThreads, bool cancelsDuringWork) { TaskCompletionSource <object> taskBlocker1 = new TaskCompletionSource <object>(); bool completed = false; void DoMockWorkBlocking(MockWorkIn work, CancellationToken token) { taskBlocker1.Task.Wait(); Task.Delay(1, token).Wait(); completed = true; } CancellationTokenSource ts = new CancellationTokenSource(); var cfg = new MultiThreadedWorkerConfig(totThreads); MultiThreadedWorker <MockWorkIn> mtw = new MultiThreadedWorker <MockWorkIn>(cfg, DoMockWorkBlocking); mtw.AddWorkItem(new MockWorkIn(1), ts.Token); if (cancelsDuringWork) { ts.Cancel(); } taskBlocker1.SetResult(null); Assert.DoesNotThrow(mtw.Dispose); Assert.AreEqual(!cancelsDuringWork, completed); }
private static async Task <ExitCode> RunAllInParallel(List <Assembly> assemblies, RunOptions runOptions, uint threads) { _teamCityGlobalReporter.OnRunStart(); var worker = new MultiThreadedWorker <Assembly, ExitCode>(assemblies, (assembly) => RunAssembly(assembly, runOptions), threads); IEnumerable <ExitCode> result = await worker.Run(); FlushTeamCityOutput(); _teamCityGlobalReporter.OnRunEnd(); if (result.Any(e => e == ExitCode.Error)) { return(ExitCode.Error); } else if (result.Any(e => e == ExitCode.Failure)) { return(ExitCode.Failure); } else { return(ExitCode.Success); } }
public void AddWorkItem_Cancels(int totThreads) { MockWorker mw = new MockWorker(); CancellationTokenSource ts = new CancellationTokenSource(); var cfg = new MultiThreadedWorkerConfig(totThreads); MultiThreadedWorker <MockWorkIn> mtw = new MultiThreadedWorker <MockWorkIn>(cfg, mw.DoMockWorkBlocking); mtw.AddWorkItem(new MockWorkIn(1), ts.Token); mw.TriggerOnBlockedWorkAsync(() => ts.Cancel()).Wait(); Assert.AreEqual(1, mw.doneWork.Count(f => f.Item1)); Assert.AreEqual(1, mw.doneWork.Count()); }
public void AddWorkItem_ItemsProcessed(int totItems, int totThreads, int maxQueuedItems) { MockWorker mw = new MockWorker(); CancellationTokenSource ts = new CancellationTokenSource(); var cfg = GetConfig(totThreads, maxQueuedItems); using (MultiThreadedWorker <MockWorkIn> mtw = new MultiThreadedWorker <MockWorkIn>(cfg, mw.DoMockWork_Simple)) { foreach (int inputIx in Enumerable.Range(1, totItems)) { mtw.AddWorkItem(new MockWorkIn(inputIx), ts.Token); } mtw.Flush(ts.Token); } Assert.AreEqual(Enumerable.Range(1, totItems), mw.doneWork.Where(f => !f.Item1).OrderBy(f => f.Item2.ix).Select(f => f.Item2.ix)); }
public void AddWorkItemAsync_OneItemProcessed() { MockWorker mw = new MockWorker(); CancellationTokenSource ts = new CancellationTokenSource(); int inputIx = 1; int totThreads = 1; int maxQueuedItems = 1; var cfg = GetConfig(totThreads, maxQueuedItems); using (MultiThreadedWorker <MockWorkIn> mtw = new MultiThreadedWorker <MockWorkIn>(cfg, mw.DoMockWork_Simple)) { mtw.AddWorkItem(new MockWorkIn(inputIx), ts.Token); } Assert.AreEqual(1, mw.doneWork.Count); Assert.AreEqual(false, mw.doneWork.First().Item1); Assert.AreEqual(inputIx, mw.doneWork.First().Item2.ix); }
private static async Task<ExitCode> RunAllInParallel(List<Assembly> assemblies, RunOptions runOptions, uint threads) { _teamCityGlobalReporter.OnRunStart(); var worker = new MultiThreadedWorker<Assembly, ExitCode>(assemblies, (assembly) => RunAssembly(assembly, runOptions), threads); IEnumerable<ExitCode> result = await worker.Run(); FlushTeamCityOutput(); _teamCityGlobalReporter.OnRunEnd(); if (result.Any(e => e == ExitCode.Error)) return ExitCode.Error; else if (result.Any(e => e == ExitCode.Failure)) return ExitCode.Failure; else return ExitCode.Success; }
public TFrameList Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { if (reader.TryReadNil()) { return((TFrameList)(IList <T>)null); } Interlocked.Increment(ref ParallelGatekeeperSingleton.wrapperDepth); try { options.Security.DepthStep(ref reader); try { FrameFormatterSerializationOptions frameOptions = options.GetOptionParams(); if (frameOptions.MthWorkerConfig.MaxConcurrentTasks == 1 || ParallelGatekeeperSingleton.wrapperDepth > 1) { return(DeserializeSynchronous(ref reader, options)); } var readerBackup = reader.CreatePeekReader(); int count = reader.ReadArrayHeader(); if (count == 0) { reader = readerBackup; return(DeserializeSynchronous(ref reader, options)); } var peekreader = reader.CreatePeekReader(); if (FrameItemFormatter <T> .ReadElementHeader(ref peekreader) == Frame <T> .unassigned) { if (frameOptions.ThrowOnUnnasignedFrameDeserialization) { throw new StreamSerializationException($"Unassigned buffer length found during parallel deserialize for {nameof(TFrameList)}"); } reader = readerBackup; return(DeserializeSynchronous(ref reader, options)); } IMessagePackFormatter <T> formatterT = options.Resolver.GetFormatterWithVerify <T>(); ListFrameWrapper valueWrapper = GetTFrameListWrapper(count); Frame <T>[] resItems = valueWrapper.AsFrameArray(); BatchSizeEstimator batchEstimator = new BatchSizeEstimator(frameOptions.BatchSizeEstimatorConfig); void ProcessBatch(BatchWithBufferWritersAndElementOffset batch, CancellationToken token) { try { ReadOnlySpan <int> lengths = batch.buffers.lengths.WrittenSpan; ReadOnlyMemory <byte> bodies = batch.buffers.concatenatedBodies.WrittenMemory; int batchSize = batch.buffers.lengths.WrittenCount; var destSpan = resItems.AsSpan(batch.offset, batchSize); for (int ix = 0, bodyStartIx = 0; ix < batchSize; ix++) { int itemLen = lengths[ix]; ReadOnlyMemory <byte> body = bodies.Slice(bodyStartIx, itemLen); MessagePackReader tmpReader = new MessagePackReader(body) { CancellationToken = token }; destSpan[ix].BufferLength = body.Length; destSpan[ix].Item = formatterT.Deserialize(ref tmpReader, options); bodyStartIx += itemLen; } } finally { objPoolBufferWriterBodies.Return(batch.buffers.concatenatedBodies); objPoolBufferWriterBodyLengths.Return(batch.buffers.lengths); } } using (var mtw = new MultiThreadedWorker <BatchWithBufferWritersAndElementOffset>( frameOptions.MthWorkerConfig, ProcessBatch)) { int i = 0; while (i < count) { int batchSize = Math.Min(count - i, batchEstimator.RecomendedBatchSize); var currentBatch = new BatchWithBufferWritersAndElementOffset() { offset = i, buffers = new BatchWithBufferWriters() { concatenatedBodies = objPoolBufferWriterBodies.Get(), lengths = objPoolBufferWriterBodyLengths.Get() } }; for (int seqIx = 0; seqIx < batchSize; seqIx++) { int itemLength = FrameItemFormatter <T> .ReadElementHeader(ref reader); if (itemLength == Frame <T> .unassigned) { throw new StreamSerializationException($"Unassigned buffer length found during parallel deserialize for {nameof(TFrameList)}"); } currentBatch.buffers.lengths.GetSpan(1)[0] = itemLength; currentBatch.buffers.lengths.Advance(1); ReadOnlySequence <byte> raw = reader.ReadRaw(itemLength); raw.CopyTo(currentBatch.buffers.concatenatedBodies.GetSpan(itemLength)); currentBatch.buffers.concatenatedBodies.Advance(itemLength); batchEstimator.UpdateEstimate(itemLength); } mtw.AddWorkItem(currentBatch, reader.CancellationToken); i += batchSize; } } return(valueWrapper.AsFrameList()); } finally { reader.Depth--; } } finally { Interlocked.Decrement(ref ParallelGatekeeperSingleton.wrapperDepth); } }