예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
 /// <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);
        }
예제 #6
0
        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");
                }
            });
        }
예제 #7
0
        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.
                }
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        /// <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);
        }
예제 #12
0
        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);
                }
            });
        }
예제 #13
0
        /// <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));
        }
예제 #14
0
        /// <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);
                    }
                }
            }
        }
예제 #15
0
        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());
                        }
                    }
                }
            }
        }
예제 #16
0
        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);
        }
예제 #17
0
        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);
        }
예제 #18
0
        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);
                }
            });
        }
예제 #19
0
        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);
        }
예제 #20
0
        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);
            });
        }
예제 #22
0
        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");
            }
        }
예제 #23
0
        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);
        }
예제 #24
0
        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());
                }
            });
        }
예제 #25
0
        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 _))
     {
     }
     ;
 }
예제 #29
0
 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))
            {
            }
        }
예제 #31
0
        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);
		}
예제 #33
0
		// 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;
				}
			}
		}
예제 #34
0
		// 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);
		}
예제 #38
0
		// 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;
					}
				}
			}
		}
예제 #39
0
		// 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 ();
			}
		}