private void DoWorkAndReport(IProducerConsumerCollection <string> inputCollection, IProducerConsumerCollection <object[]> outputCollection, ManualResetEvent pauseEvent, IProgress <int> progress) { if (Delimiter == null) { var outputMessage = "Delimiter is not set for this Stringsplitter"; LogService.Instance.Error(outputMessage); throw new InvalidOperationException(outputMessage); } string[] _Delimiter = new string[] { Delimiter }; string InputString; int ProcessedCount = 0; if (Qualifier != null) { while (HasWork) { pauseEvent.WaitOne(); if (inputCollection.TryTake(out InputString)) { string[] OutputString = StringAndText.SplitRow(InputString, Delimiter, Qualifier, false); while (!outputCollection.TryAdd(OutputString)) { pauseEvent.WaitOne(); } ProcessedCount++; } else { Thread.Sleep(10); } if (ProcessedCount % 1000 == 0) { progress.Report(ProcessedCount); } } } else { while (HasWork) { pauseEvent.WaitOne(); if (inputCollection.TryTake(out InputString)) { string[] OutputString = InputString.Split(_Delimiter, StringSplitOptions.None); while (!outputCollection.TryAdd(OutputString)) { pauseEvent.WaitOne(); } ProcessedCount++; } if (ProcessedCount % 1000 == 0) { progress.Report(ProcessedCount); } } } progress.Report(ProcessedCount); }
public void TryPeek_SucceedsOnEmptyBagThatWasOnceNonEmpty() { IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(); int item; for (int i = 0; i < 2; i++) { Assert.False(TryPeek(c, out item)); Assert.Equal(0, item); } Assert.True(c.TryAdd(42)); for (int i = 0; i < 2; i++) { Assert.True(TryPeek(c, out item)); Assert.Equal(42, item); } Assert.True(c.TryTake(out item)); Assert.Equal(42, item); Assert.False(TryPeek(c, out item)); Assert.Equal(0, item); Assert.False(c.TryTake(out item)); Assert.Equal(0, item); }
public void ManyConcurrentAddsTakesPeeks_ForceContentionWithOtherThreadsTaking(double seconds) { IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(); const int MaxCount = 4; DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds); Task <long> addsTakes = ThreadFactory.StartNew(() => { long total = 0; while (DateTime.UtcNow < end) { for (int i = 1; i <= MaxCount; i++) { Assert.True(c.TryAdd(i)); total++; } int item; if (TryPeek(c, out item)) { Assert.InRange(item, 1, MaxCount); } for (int i = 1; i <= MaxCount; i++) { if (c.TryTake(out item)) { total--; Assert.InRange(item, 1, MaxCount); } } } return(total); }); Task <long> takesFromOtherThread = ThreadFactory.StartNew(() => { long total = 0; int item; while (DateTime.UtcNow < end) { if (c.TryTake(out item)) { total++; Assert.InRange(item, 1, MaxCount); } } return(total); }); WaitAllOrAnyFailed(addsTakes, takesFromOtherThread); long remaining = addsTakes.Result - takesFromOtherThread.Result; Assert.InRange(remaining, 0, long.MaxValue); Assert.Equal(remaining, c.Count); }
/// <summary>Attempts to obtain an object from the pool.</summary> /// <param name="item">The item obtained if successful, or the default value for <c>T</c> otherwise.</param> /// <returns>True if the method succeeds, false if there were </returns> public bool TryGet(out T item) { if (!_store.TryTake(out item)) { if (_factory == null) { return(false); } item = _factory(); } return(true); }
public bool Take(out T item) { if (_queue.TryTake(out item)) { return(true); } if (!_completeAdding) { _manualResetEvent.Wait(); } return(false); }
public static void RemoveStressTest(IProducerConsumerCollection <int> coll, CheckOrderingType order) { ParallelTestHelper.Repeat(delegate { const int count = 10; const int threads = 5; const int delta = 5; for (int i = 0; i < (count + delta) * threads; i++) { coll.TryAdd(i); } bool state = true; ParallelTestHelper.ParallelStressTest(coll, (q) => { int t; for (int i = 0; i < count; i++) { state &= coll.TryTake(out t); } }, threads); Assert.IsTrue(state, "#1"); Assert.AreEqual(delta * threads, coll.Count, "#2"); string actual = string.Empty; int temp; while (coll.TryTake(out temp)) { actual += temp.ToString();; } IEnumerable <int> range = Enumerable.Range(order == CheckOrderingType.Reversed ? 0 : count * threads, delta * threads); if (order == CheckOrderingType.Reversed) { range = range.Reverse(); } string expected = range.Aggregate(string.Empty, (acc, v) => acc + v); if (order == CheckOrderingType.DontCare) { CollectionAssert.AreEquivalent(expected, actual, "#3"); } else { Assert.AreEqual(expected, actual, "#3"); } }); }
public T Remove() { T item; while (underlyingColl.Count == 0 || !underlyingColl.TryTake(out item)) { if (isComplete.Value) { throw new OperationCanceledException("The BlockingCollection<T> is empty and has been marked as complete with regards to additions."); } Block(); } return(item); }
public void MonitorAndLogTrades() { while (true) { Trade nextTrade; //bool done = _tradesToLog.TryDequeue(out nextTrade);//its TryDequeue() not Dequeue() because other threads might have already emptied the queue.to check such scenarios //OR //bool done = _tradesToLog.TryPop(out nextTrade); //OR //bool done = _tradesToLog.TryTake(out nextTrade); //----OR----OR----OR----------------- bool done = _tradesToLog.TryTake(out nextTrade); if (done) { _staffLogs.LogTrade(nextTrade); Console.WriteLine( $"Processing transaction from {nextTrade.Person.Name}"); } else if (_workingDayComplete) { Console.WriteLine("No more sales to log - exiting"); return; } else { //in SINGLE THREADED : if QUEUE is empty, it means you have finished. //This is CONCURRENT : so, you don't know if you've finished because other threads might still add stuff. Console.WriteLine("No transactions available"); Thread.Sleep(500); //This is polling the Queue for more data for every 500ms.Bad practice. } } }
public void AddTakeWithAtLeastOneElementInCollection_IsEmpty_AlwaysFalse() { int items = 1000; IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(); Assert.True(c.TryAdd(0)); // make sure it's never empty var cts = new CancellationTokenSource(); // Consumer repeatedly calls IsEmpty until it's told to stop Task consumer = Task.Run(() => { while (!cts.IsCancellationRequested) { Assert.False(IsEmpty(c)); } }); // Producer enqueues/dequeues a bunch of items, then tells the consumer to stop Task producer = Task.Run(() => { int ignored; for (int i = 1; i <= items; i++) { Assert.True(c.TryAdd(i)); Assert.True(c.TryTake(out ignored)); } cts.Cancel(); }); Task.WaitAll(producer, consumer); }
public T Take() { if (IsCompletedAndEmpty) { throw new InvalidOperationException("Collection is completed."); } _takeItemSemaphore.Wait(_takeItemdCts.Token); T item; if (!_producerConsumer.TryTake(out item)) { throw new InvalidOperationException("Can not take item from the collection."); } // To free all waited for taking threads if (IsCompletedAndEmpty) { _takeItemdCts.Cancel(); } _addItemSemaphore?.Release(); return(item); }
/// <summary> /// Gets next item to be processed /// </summary> bool GetNextItem([MaybeNullWhen(false)] out T item) { TimeSpan ts = TimeSpan.Zero; TimeSpan gap = TimeSpan.FromMilliseconds(50); do { if (CancelToken.IsCancellationRequested) { item = default; return(false); } // if we have a result then take it if (items.TryTake(out item)) { return(true); } // otherwise sleep for a bit and try again Thread.Sleep(gap); ts += gap; } while (ts < threadWait); return(false); }
public static void AddStress(this IProducerConsumerCollection <int> coll) { ParallelTestTool.Repeat(() => { var amount = -1; const int count = 10; const int threads = 5; ParallelTestTool.ParallelStressTest(coll, q => { var t = Interlocked.Increment(ref amount); for (var i = 0; i < count; i++) { q.TryAdd(t); } }, threads); Assert.AreEqual(threads * count, coll.Count); var values = new int[threads]; int temp; while (coll.TryTake(out temp)) { values[temp]++; } for (var i = 0; i < threads; i++) { Assert.AreEqual(count, values[i], "#" + i); } }); }
/// <summary> /// 컬렉션으로부터 비동기적으로 요소를 취합니다. /// </summary> /// <returns>A Task that represents the element removed from the collection.</returns> public Task <T> Take() { if (IsDebugEnabled) { log.Debug("내부 버퍼에 보관된 요소를 가져갑니다..."); } return (_semaphore .WaitAsync() .ContinueWith(_ => { T result; if (_collection.TryTake(out result) == false) { throw new InvalidOperationException("컬렉션에서 요소를 가져오지 못했습니다."); } if (IsDebugEnabled) { log.Debug("내부 버퍼에 보관된 요소를 꺼냈습니다... result=[{0}]", result); } return result; }, TaskContinuationOptions.ExecuteSynchronously)); }
/// <summary> /// The method that will actually execute the logic of the executor. /// It is responsible for the correct running condition (i.e. when it should be stopped), taking sources, processing them, /// and activating the corresponding events for <see cref="LifeCycleEvent"/>. /// </summary> protected virtual void PipelineExecution_Thread() { while (IsRunning || PendingFileSources.Count > 0) { _queuedSemaphore.Wait(); IFileSource source; // when forcing the thread to stop, we release the semaphore without // actually adding an element, causing it to continue and break the loop lock (ActiveFileSources) { // ensure that the element is either active or pending if (!PendingFileSources.TryTake(out source)) { continue; } ActiveFileSources.Add(source); } ProcessSource(source); lock (ActiveFileSources) { if (ActiveFileSources.Remove(source)) { ReleaseConflicts(source); } } } }
public void GetEnumerator_EnumerationsAreSnapshots() { IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(); Assert.Empty(c); using (IEnumerator <int> e1 = c.GetEnumerator()) { Assert.True(c.TryAdd(1)); using (IEnumerator <int> e2 = c.GetEnumerator()) { Assert.True(c.TryAdd(2)); using (IEnumerator <int> e3 = c.GetEnumerator()) { int item; Assert.True(c.TryTake(out item)); using (IEnumerator <int> e4 = c.GetEnumerator()) { Assert.False(e1.MoveNext()); Assert.True(e2.MoveNext()); Assert.False(e2.MoveNext()); Assert.True(e3.MoveNext()); Assert.True(e3.MoveNext()); Assert.False(e3.MoveNext()); Assert.True(e4.MoveNext()); Assert.False(e4.MoveNext()); } } } } }
public void ManyConcurrentAddsTakes_ForceContentionWithGetEnumerator(int initialCount, double seconds) { IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(Enumerable.Range(1, initialCount)); const int MaxCount = 4; DateTime end = DateTime.UtcNow + TimeSpan.FromSeconds(seconds); Task addsTakes = ThreadFactory.StartNew(() => { while (DateTime.UtcNow < end) { for (int i = 1; i <= MaxCount; i++) { Assert.True(c.TryAdd(i)); } for (int i = 1; i <= MaxCount; i++) { int item; Assert.True(c.TryTake(out item)); Assert.InRange(item, 1, MaxCount); } } }); while (DateTime.UtcNow < end) { int[] arr = c.Select(i => i).ToArray(); Assert.InRange(arr.Length, initialCount, MaxCount + initialCount); Assert.DoesNotContain(0, arr); // make sure we didn't get default(T) } addsTakes.GetAwaiter().GetResult(); Assert.Equal(initialCount, c.Count); }
public void Add_TakeFromAnotherThread_ExpectedItemsTaken() { IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(); Assert.True(IsEmpty(c)); Assert.Equal(0, c.Count); const int NumItems = 100000; Task producer = Task.Run(() => Parallel.For(1, NumItems + 1, i => Assert.True(c.TryAdd(i)))); var hs = new HashSet <int>(); while (hs.Count < NumItems) { int item; if (c.TryTake(out item)) { hs.Add(item); } } producer.GetAwaiter().GetResult(); Assert.True(IsEmpty(c)); Assert.Equal(0, c.Count); AssertSetsEqual(new HashSet <int>(Enumerable.Range(1, NumItems)), hs); }
public static void AddStressTest(IProducerConsumerCollection <int> coll) { ParallelTestHelper.Repeat(delegate { int amount = -1; const int count = 10; const int threads = 5; ParallelTestHelper.ParallelStressTest(coll, (q) => { int t = Interlocked.Increment(ref amount); for (int i = 0; i < count; i++) { coll.TryAdd(t); } }, threads); Assert.AreEqual(threads * count, coll.Count, "#-1"); int[] values = new int[threads]; int temp; while (coll.TryTake(out temp)) { values[temp]++; } for (int i = 0; i < threads; i++) { Assert.AreEqual(count, values[i], "#" + i); } }); }
private void DoWorkAndReport(IProducerConsumerCollection <string> inputCollection, IProducerConsumerCollection <object[]> outputCollection, ManualResetEvent pauseEvent, IProgress <int> progress) { string[] _Delimiter = this._Delimiter; string InputString; int ProcessedCount = 0; while (HasWork) { pauseEvent.WaitOne(); if (inputCollection.TryTake(out InputString)) { string[] OutputString = InputString.Split(_Delimiter, StringSplitOptions.None); while (!outputCollection.TryAdd(OutputString)) { pauseEvent.WaitOne(); } ProcessedCount++; } if (ProcessedCount % 1000 == 0) { progress.Report(ProcessedCount); } } progress.Report(ProcessedCount); }
public void Initialize_ThenTakeOrPeekInParallel_ItemsObtainedAsExpected(int numStartingItems, int threadsCount, int itemsPerThread, bool take) { IProducerConsumerCollection <int> c = CreateProducerConsumerCollection(Enumerable.Range(1, numStartingItems)); int successes = 0; using (var b = new Barrier(threadsCount)) { WaitAllOrAnyFailed(Enumerable.Range(0, threadsCount).Select(threadNum => ThreadFactory.StartNew(() => { b.SignalAndWait(); for (int j = 0; j < itemsPerThread; j++) { int data; if (take ? c.TryTake(out data) : TryPeek(c, out data)) { Interlocked.Increment(ref successes); Assert.NotEqual(0, data); // shouldn't be default(T) } } })).ToArray()); } Assert.Equal( take ? numStartingItems : threadsCount * itemsPerThread, successes); }
public static void AddStressTest(IProducerConsumerCollection<int> coll) { ParallelTestHelper.Repeat(delegate { int amount = -1; const int count = 10; const int threads = 5; ParallelTestHelper.ParallelStressTest(coll, (q) => { int t = Interlocked.Increment(ref amount); for (int i = 0; i < count; i++) coll.TryAdd(t); }, threads); Assert.AreEqual(threads * count, coll.Count, "#-1"); int[] values = new int[threads]; int temp; while (coll.TryTake(out temp)) { values[temp]++; } for (int i = 0; i < threads; i++) Assert.AreEqual(count, values[i], "#" + i); }); }
public static void RTest8_Interfaces() { ConcurrentBag <int> bag = new ConcurrentBag <int>(); //IPCC IProducerConsumerCollection <int> ipcc = bag as IProducerConsumerCollection <int>; Assert.False(ipcc == null, "RTest8_Interfaces: ConcurrentBag<T> doesn't implement IPCC<T>"); Assert.True(ipcc.TryAdd(1), "RTest8_Interfaces: IPCC<T>.TryAdd failed"); Assert.Equal(1, bag.Count); int result = -1; Assert.True(ipcc.TryTake(out result), "RTest8_Interfaces: IPCC<T>.TryTake failed"); Assert.True(1 == result, "RTest8_Interfaces: IPCC<T>.TryTake failed"); Assert.Equal(0, bag.Count); //ICollection ICollection collection = bag as ICollection; Assert.False(collection == null, "RTest8_Interfaces: ConcurrentBag<T> doesn't implement ICollection"); Assert.False(collection.IsSynchronized, "RTest8_Interfaces: IsSynchronized returned true"); //IEnumerable IEnumerable enumerable = bag as IEnumerable; Assert.False(enumerable == null, "RTest8_Interfaces: ConcurrentBag<T> doesn't implement IEnumerable"); foreach (object o in enumerable) { Assert.True(false, "RTest8_Interfaces: Enumerable returned items when the bag is empty"); } }
public static void Test9_Interfaces() { ConcurrentStack <int> stack = new ConcurrentStack <int>(); IProducerConsumerCollection <int> ipcc = stack; Assert.Equal(0, ipcc.Count); int item; Assert.False(ipcc.TryTake(out item)); Assert.True(ipcc.TryAdd(1)); ICollection collection = stack; Assert.False(collection.IsSynchronized); stack.Push(1); int count = stack.Count; IEnumerable enumerable = stack; foreach (object o in enumerable) { count--; } Assert.Equal(0, count); }
public static void AddStressTest(IProducerConsumerCollection <int> coll) { ParallelTestHelper.Repeat(delegate { var amount = -1; const int Count = 10; const int Threads = 5; ParallelTestHelper.ParallelStressTest(coll, (q) => { var t = Interlocked.Increment(ref amount); for (var i = 0; i < Count; i++) { coll.TryAdd(t); } }, Threads); Assert.AreEqual(Threads * Count, coll.Count, "#-1"); var values = new int[Threads]; int temp; while (coll.TryTake(out temp)) { values[temp]++; } for (var i = 0; i < Threads; i++) { Assert.AreEqual(Count, values[i], "#" + i.ToString()); } }); }
public static void Test6_Interfaces() { ConcurrentQueue <int> queue = new ConcurrentQueue <int>(); int item; IProducerConsumerCollection <int> ipcc = queue; Assert.Equal(0, ipcc.Count); Assert.False(ipcc.TryTake(out item), "TestIPCC: IPCC.TryTake returned true when the collection is empty"); Assert.True(ipcc.TryAdd(1)); ICollection collection = queue; Assert.False(collection.IsSynchronized); queue.Enqueue(1); int count = queue.Count; IEnumerable enumerable = queue; foreach (object o in enumerable) { count--; } Assert.Equal(0, count); }
public Publication Dequeue() { Publication pub; _queue.TryTake(out pub); return(pub); }
private Task <T> TakeAsync <TAwaiterFactory>(TAwaiterFactory awaiterFactory) where TAwaiterFactory : IAwaiterFactory <T> { long balanceAfterCurrentAwaiter = Interlocked.Decrement(ref _queueBalance); if (balanceAfterCurrentAwaiter < 0) { // Awaiters are dominating, so we can safely add a new awaiter to the queue. IAwaiter <T> awaiter = awaiterFactory.CreateAwaiter(); _awaiterQueue.Enqueue(awaiter); return(awaiter.Task); } else { // There's at least one item available or being added, so we're returning it directly. T item; SpinWait spin = new SpinWait(); while (!_itemQueue.TryTake(out item)) { spin.SpinOnce(); } return(Task.FromResult(item)); } }
/// <summary>Clears the collection by repeatedly taking elements until it's empty.</summary> /// <typeparam name="T">Specifies the type of the elements in the collection.</typeparam> /// <param name="collection">The collection to be cleared.</param> public static void Clear <T>(this IProducerConsumerCollection <T> collection) { while (collection.TryTake(out _)) { } ; }
public static bool TryTakeAndIgnore <T>(this IProducerConsumerCollection <T> producerConsumerCollection) { if (producerConsumerCollection == null) { throw new ArgumentNullException(nameof(producerConsumerCollection)); } return(producerConsumerCollection.TryTake(out _)); }
/// <summary>Clears the collection by repeatedly taking elements until it's empty.</summary> /// <typeparam name="T">Specifies the type of the elements in the collection.</typeparam> /// <param name="collection">The collection to be cleared.</param> public static void Clear <T>(this IProducerConsumerCollection <T> collection) { T local; while (collection.TryTake(out local)) { } }
public static void Clear <T>(this IProducerConsumerCollection <T> collection) { T item; while (collection.TryTake(out item)) { } }
private IMessagingChannel TryConnect(string channelGroup, IProducerConsumerCollection<IMessagingChannel> items) { IMessagingChannel channel; if (!items.TryTake(out channel)) { Log.Debug("No available channel in the pool for '{0}', establishing a new channel.", channelGroup); channel = this.connector.Connect(channelGroup); } Log.Verbose("Resolving channel for '{0}' from the pool of available channels.", channelGroup); this.open.TryAdd(channel, true); return new PooledDispatchChannel(this, channel, this.currentToken); }
// Almost same as above but with an added predicate and treating one item at a time. // It's used by Scheduler Participate(...) method for special waiting case like // Task.WaitAll(someTasks) or Task.WaitAny(someTasks) // Predicate should be really fast and not blocking as it is called a good deal of time // Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default) public static void ParticipativeWorkerMethod (Task self, ManualResetEventSlim predicateEvt, int millisecondsTimeout, IProducerConsumerCollection<Task> sharedWorkQueue, ThreadWorker[] others, ManualResetEvent evt, Func<Task, Task, bool> checkTaskFitness) { const int stage1 = 5, stage2 = 0; int tries = 50; WaitHandle[] handles = null; Watch watch = Watch.StartNew (); if (millisecondsTimeout == -1) millisecondsTimeout = int.MaxValue; bool aggressive = false; bool hasAutoReference = autoReference != null; Action<Task> adder = null; while (!predicateEvt.IsSet && watch.ElapsedMilliseconds < millisecondsTimeout && !self.IsCompleted) { // We try to execute the self task as it may be the simplest way to unlock // the situation if (self.Status == TaskStatus.WaitingToRun) { self.Execute (hasAutoReference ? autoReference.adder : (Action<Task>)null); if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } Task value; // If we are in fact a normal ThreadWorker, use our own deque if (hasAutoReference) { var enumerable = autoReference.dDeque.GetEnumerable (); if (adder == null) adder = hasAutoReference ? autoReference.adder : (Action<Task>)null; if (enumerable != null) { foreach (var t in enumerable) { if (t == null) continue; if (checkTaskFitness (self, t)) t.Execute (adder); if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } } } int count = sharedWorkQueue.Count; // Dequeue only one item as we have restriction while (--count >= 0 && sharedWorkQueue.TryTake (out value) && value != null) { evt.Set (); if (checkTaskFitness (self, value) || aggressive) value.Execute (null); else { if (autoReference == null) sharedWorkQueue.TryAdd (value); else autoReference.dDeque.PushBottom (value); evt.Set (); } if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } // First check to see if we comply to predicate if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; // Try to complete other work by stealing since our desired tasks may be in other worker ThreadWorker other; for (int i = 0; i < others.Length; i++) { if ((other = others [i]) == autoReference || other == null) continue; if (other.dDeque.PopTop (out value) == PopResult.Succeed && value != null) { evt.Set (); if (checkTaskFitness (self, value) || aggressive) value.Execute (null); else { if (autoReference == null) sharedWorkQueue.TryAdd (value); else autoReference.dDeque.PushBottom (value); evt.Set (); } } if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } /* Waiting is split in 4 phases * - until stage 1 we simply yield the thread to let others add data * - between stage 1 and stage2 we use ManualResetEventSlim light waiting mechanism * - after stage2 we fall back to the heavier WaitHandle waiting mechanism * - if really the situation isn't evolving after a couple of sleep, we disable * task fitness check altogether */ if (--tries > stage1) Thread.Yield (); else if (tries >= stage2) predicateEvt.Wait (ComputeTimeout (5, millisecondsTimeout, watch)); else { if (tries == stage2 - 1) handles = new [] { predicateEvt.WaitHandle, evt }; System.Threading.WaitHandle.WaitAny (handles, ComputeTimeout (1000, millisecondsTimeout, watch)); if (tries == stage2 - 10) aggressive = true; } } }
// Almost same as above but with an added predicate and treating one item at a time. // It's used by Scheduler Participate(...) method for special waiting case like // Task.WaitAll(someTasks) or Task.WaitAny(someTasks) // Predicate should be really fast and not blocking as it is called a good deal of time // Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default) public static void ParticipativeWorkerMethod (Task self, ManualResetEventSlim predicateEvt, int millisecondsTimeout, IProducerConsumerCollection<Task> sharedWorkQueue, ThreadWorker[] others, ManualResetEvent evt) { const int stage1 = 5, stage2 = 0; int tries = 8; WaitHandle[] handles = null; Watch watch = Watch.StartNew (); if (millisecondsTimeout == -1) millisecondsTimeout = int.MaxValue; while (!predicateEvt.IsSet && watch.ElapsedMilliseconds < millisecondsTimeout) { Task value; // If we are in fact a normal ThreadWorker, use our own deque if (autoReference != null) { while (autoReference.dDeque.PopBottom (out value) == PopResult.Succeed && value != null) { evt.Set (); if (CheckTaskFitness (self, value)) value.Execute (autoReference.ChildWorkAdder); else { sharedWorkQueue.TryAdd (value); evt.Set (); } if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } } int count = sharedWorkQueue.Count; // Dequeue only one item as we have restriction while (--count >= 0 && sharedWorkQueue.TryTake (out value) && value != null) { evt.Set (); if (CheckTaskFitness (self, value)) value.Execute (null); else { if (autoReference == null) sharedWorkQueue.TryAdd (value); else autoReference.dDeque.PushBottom (value); evt.Set (); } if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } // First check to see if we comply to predicate if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; // Try to complete other work by stealing since our desired tasks may be in other worker ThreadWorker other; for (int i = 0; i < others.Length; i++) { if ((other = others [i]) == autoReference || other == null) continue; if (other.dDeque.PopTop (out value) == PopResult.Succeed && value != null) { evt.Set (); if (CheckTaskFitness (self, value)) value.Execute (null); else { if (autoReference == null) sharedWorkQueue.TryAdd (value); else autoReference.dDeque.PushBottom (value); evt.Set (); } } if (predicateEvt.IsSet || watch.ElapsedMilliseconds > millisecondsTimeout) return; } if (--tries > stage1) Thread.Yield (); else if (tries >= stage2) predicateEvt.Wait (ComputeTimeout (100, millisecondsTimeout, watch)); else { if (tries == stage2 - 1) handles = new [] { predicateEvt.WaitHandle, evt }; WaitHandle.WaitAny (handles, ComputeTimeout (1000, millisecondsTimeout, watch)); } } }
public static void RemoveStressTest (IProducerConsumerCollection<int> coll, CheckOrderingType order) { ParallelTestHelper.Repeat (delegate { const int count = 10; const int threads = 5; const int delta = 5; for (int i = 0; i < (count + delta) * threads; i++) coll.TryAdd (i); bool state = true; ParallelTestHelper.ParallelStressTest (coll, (q) => { int t; for (int i = 0; i < count; i++) state &= coll.TryTake (out t); }, threads); Assert.IsTrue (state, "#1"); Assert.AreEqual (delta * threads, coll.Count, "#2"); string actual = string.Empty; int temp; while (coll.TryTake (out temp)) { actual += temp.ToString ();; } IEnumerable<int> range = Enumerable.Range (order == CheckOrderingType.Reversed ? 0 : count * threads, delta * threads); if (order == CheckOrderingType.Reversed) range = range.Reverse (); string expected = range.Aggregate (string.Empty, (acc, v) => acc + v); if (order == CheckOrderingType.DontCare) CollectionAssert.AreEquivalent (expected, actual, "#3"); else Assert.AreEqual (expected, actual, "#3"); }); }
private static void TestSendNotifyCore( IPEndPoint endPoint, CountdownEvent arrivalLatch, IProducerConsumerCollection<string> arrivedIds, int count ) { using ( var udpClient = new UdpClient( AddressFamily.InterNetwork ) ) using ( var concurrencyLatch = new CountdownEvent( arrivalLatch.InitialCount ) ) { udpClient.Connect( endPoint ); for ( int i = 0; i < count; i++ ) { if ( concurrencyLatch != null ) { concurrencyLatch.Reset(); } arrivalLatch.Reset(); // Clear ids. string dummy; while ( arrivedIds.TryTake( out dummy ) ) { } var ids = Enumerable.Repeat( 0, concurrencyLatch == null ? 1 : concurrencyLatch.InitialCount ).Select( _ => Guid.NewGuid().ToString() ).ToArray(); if ( !Task.WaitAll( ids.Select( id => Task.Factory.StartNew( _ => { using ( var buffer = new MemoryStream() ) { using ( var packer = Packer.Create( buffer, false ) ) { PackRequest( packer, id ); } buffer.Position = 0; if ( concurrencyLatch != null ) { concurrencyLatch.Signal(); if ( !concurrencyLatch.Wait( Debugger.IsAttached ? Timeout.Infinite : TimeoutMilliseconds ) ) { throw new TimeoutException(); } } // send udpClient.Send( buffer.ToArray(), ( int )buffer.Length ); } }, id ) ).ToArray(), Debugger.IsAttached ? Timeout.Infinite : TimeoutMilliseconds ) ) { throw new TimeoutException(); } // wait if ( !arrivalLatch.Wait( Debugger.IsAttached ? Timeout.Infinite : TimeoutMilliseconds ) ) { throw new TimeoutException(); } Assert.That( arrivedIds, Is.EquivalentTo( ids ) ); } } }
public static void RemoveStressTest (IProducerConsumerCollection<int> coll, CheckOrderingType order) { ParallelTestHelper.Repeat (delegate { const int count = 10; const int threads = 5; const int delta = 5; for (int i = 0; i < (count + delta) * threads; i++) while (!coll.TryAdd (i)); bool state = true; Assert.AreEqual ((count + delta) * threads, coll.Count, "#0"); ParallelTestHelper.ParallelStressTest (coll, (q) => { bool s = true; int t; for (int i = 0; i < count; i++) { s &= coll.TryTake (out t); // try again in case it was a transient failure if (!s && coll.TryTake (out t)) s = true; } if (!s) state = false; }, threads); Assert.IsTrue (state, "#1"); Assert.AreEqual (delta * threads, coll.Count, "#2"); string actual = string.Empty; int temp; while (coll.TryTake (out temp)) { actual += temp.ToString ();; } IEnumerable<int> range = Enumerable.Range (order == CheckOrderingType.Reversed ? 0 : count * threads, delta * threads); if (order == CheckOrderingType.Reversed) range = range.Reverse (); string expected = range.Aggregate (string.Empty, (acc, v) => acc + v); if (order == CheckOrderingType.DontCare) Assert.That (actual, new CollectionEquivalentConstraint (expected), "#3"); else Assert.AreEqual (expected, actual, "#3"); }, 1000); }
// Almost same as above but with an added predicate and treating one item at a time. // It's used by Scheduler Participate(...) method for special waiting case like // Task.WaitAll(someTasks) or Task.WaitAny(someTasks) // Predicate should be really fast and not blocking as it is called a good deal of time // Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default) public static void WorkerMethod (Func<bool> predicate, IProducerConsumerCollection<Task> sharedWorkQueue, ThreadWorker[] others) { while (!predicate ()) { Task value; // Dequeue only one item as we have restriction if (sharedWorkQueue.TryTake (out value)) { if (value != null) { if (CheckTaskFitness (value)) value.Execute (null); else sharedWorkQueue.TryAdd (value); } } // First check to see if we comply to predicate if (predicate ()) { return; } // Try to complete other work by stealing since our desired tasks may be in other worker ThreadWorker other; for (int i = 0; i < others.Length; i++) { if ((other = others [i]) == null) continue; if (other.dDeque.PopTop (out value) == PopResult.Succeed) { if (value != null) { if (CheckTaskFitness (value)) value.Execute (null); else sharedWorkQueue.TryAdd (value); } } if (predicate ()) { return; } } } }
// Almost same as above but with an added predicate and treating one item at a time. // It's used by Scheduler Participate(...) method for special waiting case like // Task.WaitAll(someTasks) or Task.WaitAny(someTasks) // Predicate should be really fast and not blocking as it is called a good deal of time // Also, the method skip tasks that are LongRunning to avoid blocking (Task are not LongRunning by default) public static void WorkerMethod (Func<bool> predicate, IProducerConsumerCollection<Task> sharedWorkQueue, ThreadWorker[] others, ManualResetEvent evt) { while (!predicate ()) { Task value; // If we are in fact a normal ThreadWorker, use our own deque if (autoReference != null) { while (autoReference.dDeque.PopBottom (out value) == PopResult.Succeed && value != null) { evt.Set (); if (CheckTaskFitness (value)) value.Execute (autoReference.ChildWorkAdder); else { autoReference.dDeque.PushBottom (value); evt.Set (); } if (predicate ()) return; } } // Dequeue only one item as we have restriction while (sharedWorkQueue.TryTake (out value) && value != null) { evt.Set (); if (CheckTaskFitness (value)) value.Execute (null); else { sharedWorkQueue.TryAdd (value); evt.Set (); } if (predicate ()) return; } // First check to see if we comply to predicate if (predicate ()) return; // Try to complete other work by stealing since our desired tasks may be in other worker ThreadWorker other; for (int i = 0; i < others.Length; i++) { if ((other = others [i]) == null) continue; if (other.dDeque.PopTop (out value) == PopResult.Succeed && value != null) { evt.Set (); if (CheckTaskFitness (value)) value.Execute (null); else { sharedWorkQueue.TryAdd (value); evt.Set (); } } if (predicate ()) return; } Thread.Yield (); } }