예제 #1
0
        public void TestAwaitThroughSyncContext()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, 2 * Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                bool isNotFailed  = false;
                bool isThreadPool = false;

                testInst.Run(() =>
                {
                    var task = AwaitThroughSyncContext();
                    task.ContinueWith(t =>
                    {
                        Volatile.Write(ref isNotFailed, !t.IsFaulted);
                        Volatile.Write(ref isThreadPool, testInst.IsThreadPoolThread);
                    }, TaskContinuationOptions.ExecuteSynchronously).Wait();
                });

                testInst.Dispose(true, true, false);

                Assert.IsTrue(isNotFailed, "isNotFailed");
                Assert.IsTrue(isThreadPool, "isThreadPool");
            }
        }
예제 #2
0
        public void TestQueueCapacityBound()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, 10, "name"))
            {
                Assert.AreEqual(10, testInst.QueueCapacity);

                int tryRunWorkItem = 100 * testInst.QueueCapacity;
                int runWorkCount   = 0;
                int executedWork   = 0;

                for (int i = 0; i < tryRunWorkItem; i++)
                {
                    if (testInst.TryRun(() =>
                    {
                        Thread.Sleep(500);
                        Interlocked.Increment(ref executedWork);
                    }))
                    {
                        runWorkCount++;
                    }
                }

                testInst.Dispose(true, true, true);
                Assert.IsTrue(runWorkCount > 0);
                Assert.IsTrue(runWorkCount < tryRunWorkItem);
                Assert.AreEqual(runWorkCount, executedWork);
            }
        }
예제 #3
0
        //=============================


        private void RunSimpleProcessWorkTest(int minThreadCount, int maxThreadCount, int queueCapacity, int workCount = 100000)
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(minThreadCount, maxThreadCount, queueCapacity, "name"))
            {
                Assert.IsTrue(testInst.ThreadCount >= minThreadCount);
                Assert.IsTrue(testInst.ActiveThreadCount >= minThreadCount);
                Assert.AreEqual(queueCapacity, testInst.QueueCapacity);
                Assert.IsTrue(testInst.IsWork);

                int expectedWork = workCount;
                int executedWork = 0;

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        Interlocked.Increment(ref executedWork);
                    });
                }

                testInst.Dispose(true, true, true);

                Assert.AreEqual(0, testInst.ThreadCount);
                Assert.IsFalse(testInst.IsWork);
                Assert.AreEqual(expectedWork, executedWork);

                testInst.CompleteAdding();
            }
        }
예제 #4
0
        public void TestLongProcessWork()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, 100, "name"))
            {
                Assert.AreEqual(100, testInst.QueueCapacity);

                int expectedWork = 100;
                int executedWork = 0;

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(250);
                        Interlocked.Increment(ref executedWork);
                    });
                }

                testInst.Dispose(true, true, true);

                Assert.AreEqual(0, testInst.ThreadCount);
                Assert.AreEqual(0, testInst.ActiveThreadCount);
                Assert.IsFalse(testInst.IsWork);
                Assert.AreEqual(expectedWork, executedWork);
            }
        }
예제 #5
0
        public void WaitUntilStopWorkCorrect()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name"))
            {
                Assert.AreEqual(-1, testInst.QueueCapacity);

                int expectedWork = 100;
                int executedWork = 0;

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(200);
                        Interlocked.Increment(ref executedWork);
                    });
                }

                testInst.Dispose(false, true, false);
                Assert.IsTrue(executedWork < expectedWork);
                Assert.IsTrue(testInst.State == ThreadPoolState.StopRequested);

                testInst.WaitUntilStop();
                Assert.IsTrue(testInst.State == ThreadPoolState.Stopped);
                Assert.AreEqual(expectedWork, executedWork);
            }
        }
예제 #6
0
 public AsyncTaskModule(QueueConfiguration configuration)
 {
     _tasks      = new List <AsyncData>();
     _threadPool = new DynamicThreadPool(1, configuration.ProcessotCount, configuration.MaxSizeQueue, "AsyncTaskModule");
     _lock       = new ReaderWriterLockSlim();
     _event      = new AutoResetEvent(false);
     _token      = new CancellationTokenSource();
 }
예제 #7
0
 public void TestSwitchToPoolWork()
 {
     using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name"))
     {
         var task = TestSwitchToPoolWorkInner(testInst);
         task.Wait();
         Assert.IsFalse(task.IsFaulted);
     }
 }
예제 #8
0
        private async Task TestSwitchToPoolWorkInner(DynamicThreadPool testInst)
        {
            Assert.IsFalse(testInst.IsThreadPoolThread);
            //Assert.IsNull(SynchronizationContext.Current);

            await testInst.SwitchToPool();

            Assert.IsTrue(testInst.IsThreadPoolThread);
            //Assert.IsNotNull(SynchronizationContext.Current);
        }
예제 #9
0
 public void RunComplexTest()
 {
     using (DynamicThreadPool testInst = new DynamicThreadPool(0, 4 * Environment.ProcessorCount, 1000, "name"))
     {
         RunTestOnPool(testInst, 4000000, 1000, 2, 10, false);
         RunTestOnPool(testInst, 4000000, 10, 2, 1000, false);
         RunTestOnPool(testInst, 4000000, 0, 2, 0, true);
         RunTestOnPool(testInst, 4000000, 0, Environment.ProcessorCount, 0, false);
     }
 }
예제 #10
0
        public static void RunThreads(Action work)
        {
            var _settings_pool = new DynamicThreadPoolOptions().UseOwnTaskScheduler;
            var _threadPool    = new DynamicThreadPool(1, 1, "threads");

            for (var i = 0; i < 1; i++)
            {
                _threadPool.Run(work);
                // Thread.Sleep(100000);
            }
        }
예제 #11
0
        public void TestCantAddAfterCompleteAdding()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name"))
            {
                Assert.IsTrue(testInst.TryRun(() => { }));

                testInst.CompleteAdding();

                Assert.IsFalse(testInst.TryRun(() => { }));

                testInst.Run(() => { });
            }
        }
예제 #12
0
        public void TestTryRunWork()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, 100, "name"))
            {
                int  wasExecuted = 0;
                bool wasRunned   = testInst.TryRun(() =>
                {
                    Interlocked.Exchange(ref wasExecuted, 1);
                });

                Assert.IsTrue(wasRunned);
                TimingAssert.AreEqual(5000, 1, () => Volatile.Read(ref wasExecuted));
            }
        }
예제 #13
0
        public void DynamicThreadPoolFillUpToWork()
        {
            TestContext.WriteLine("Test trace message");

            using (DynamicThreadPool testInst = new DynamicThreadPool(0, 4 * Environment.ProcessorCount, 1000, "name"))
            {
                Assert.AreEqual(0, testInst.ActiveThreadCount);

                testInst.FillPoolUpTo(Environment.ProcessorCount);
                Assert.AreEqual(Environment.ProcessorCount, testInst.ActiveThreadCount);
                Assert.AreEqual(Environment.ProcessorCount, testInst.ThreadCount);

                testInst.FillPoolUpTo(4 * Environment.ProcessorCount);
                Assert.AreEqual(4 * Environment.ProcessorCount, testInst.ThreadCount);
            }
        }
예제 #14
0
        public void TestTaskSchedulerSetted()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                AtomicBool isPropperSceduller = new AtomicBool(false);

                testInst.Run(() =>
                {
                    isPropperSceduller.Value = TaskScheduler.Current == testInst.TaskScheduler;
                });

                TimingAssert.IsTrue(10000, isPropperSceduller, "isPropperSceduller");
                testInst.Dispose(true, true, false);
            }
        }
예제 #15
0
        public void TestTaskSchedulerWork()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                bool firstTaskInPool  = false;
                bool secondTaskInPool = false;

                var task = testInst.RunAsTask(() =>
                {
                    firstTaskInPool = testInst.IsThreadPoolThread;
                }).ContinueWith(t =>
                {
                    secondTaskInPool = testInst.IsThreadPoolThread;
                }, testInst.TaskScheduler);

                task.Wait();
                Assert.IsTrue(firstTaskInPool);
                Assert.IsTrue(secondTaskInPool);
            }
        }
예제 #16
0
        public void TestNoSyncContextAndTaskSchedullerWhenNotConfigurated()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = false, UseOwnSyncContext = false
            }))
            {
                var defSyncContext    = SynchronizationContext.Current;
                var defTaskScheduller = TaskScheduler.Current;

                AtomicBool isDefaultSyncContext    = new AtomicBool(false);
                AtomicBool isDefaultTaskScheduller = new AtomicBool(false);

                testInst.Run(() =>
                {
                    isDefaultSyncContext.Value    = SynchronizationContext.Current == defSyncContext;
                    isDefaultTaskScheduller.Value = TaskScheduler.Current == defTaskScheduller;
                });

                TimingAssert.IsTrue(10000, isDefaultSyncContext, "isDefaultSyncContext");
                TimingAssert.IsTrue(10000, isDefaultTaskScheduller, "isDefaultTaskScheduller");
                testInst.Dispose(true, true, false);
            }
        }
예제 #17
0
        public void TestSyncContextSetted()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, -1, "name", false, new DynamicThreadPoolOptions()
            {
                UseOwnTaskScheduler = true, UseOwnSyncContext = true
            }))
            {
                AtomicBool isPropperSyncContext = new AtomicBool(false);

                testInst.Run(() =>
                {
                    if (SynchronizationContext.Current != null)
                    {
                        SynchronizationContext.Current.Post((st) =>
                        {
                            isPropperSyncContext.Value = testInst.IsThreadPoolThread;
                        }, null);
                    }
                });

                TimingAssert.IsTrue(10000, isPropperSyncContext, "isPropperSyncContext");
                testInst.Dispose(true, true, false);
            }
        }
예제 #18
0
        public void TestQueueCapacityBoundExtends()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, Environment.ProcessorCount, 10, "name"))
            {
                int expectedWork = 25 + Environment.ProcessorCount;
                int executedWork = 0;

                ManualResetEventSlim tracker = new ManualResetEventSlim();

                for (int i = 0; i < expectedWork; i++)
                {
                    testInst.Run(() =>
                    {
                        tracker.Wait();
                        Interlocked.Increment(ref executedWork);
                    });
                }

                tracker.Set();

                testInst.Dispose(true, true, true);
                Assert.AreEqual(expectedWork, executedWork);
            }
        }
예제 #19
0
        public void DynamicThreadPoolPerformBalancing()
        {
            using (DynamicThreadPool testInst = new DynamicThreadPool(0, 4 * Environment.ProcessorCount, 1000, "name"))
            {
                Assert.AreEqual(0, testInst.ActiveThreadCount);

                // ========== Проверяем, что число потоков увеличивается автоматически от нуля ===========

                int executedTaskCount = 0;

                for (int i = 0; i < 1000; i++)
                {
                    testInst.Run(() =>
                    {
                        Interlocked.Increment(ref executedTaskCount);
                    });
                }

                TimingAssert.AreEqual(5000, 1000, () => Volatile.Read(ref executedTaskCount));
                Assert.IsTrue(testInst.ActiveThreadCount > 0, "1. testInst.ActiveThreadCount > 0");

                // ======== Проверяем, что на большом числе задач он рано или поздно дойдёт до числа потоков равного числу ядер ===========

                executedTaskCount = 0;
                for (int i = 0; i < testInst.MaxThreadCount * testInst.QueueCapacity; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(1);
                        Interlocked.Increment(ref executedTaskCount);
                    });
                }


                TimingAssert.AreEqual(15000, testInst.MaxThreadCount * testInst.QueueCapacity, () => Volatile.Read(ref executedTaskCount));
                Assert.IsTrue(testInst.ActiveThreadCount >= Environment.ProcessorCount, "2. testInst.ActiveThreadCount >= Environment.ProcessorCount");


                // ======== Проверяем, что на долгих задачах число потоков может стать больше числа ядер ===========

                executedTaskCount = 0;
                for (int i = 0; i < 1000; i++)
                {
                    testInst.Run(() =>
                    {
                        Thread.Sleep(20);
                        Interlocked.Increment(ref executedTaskCount);
                    });
                }


                TimingAssert.IsTrue(30000, () => Volatile.Read(ref executedTaskCount) >= 500);

                Assert.IsTrue(testInst.ActiveThreadCount > Environment.ProcessorCount, "3. testInst.ActiveThreadCount > Environment.ProcessorCount");
                Assert.IsTrue(testInst.ActiveThreadCount <= testInst.MaxThreadCount, "3. testInst.ActiveThreadCount <= testInst.MaxThreadCount");

                TimingAssert.AreEqual(30000, 1000, () => Volatile.Read(ref executedTaskCount));

                TimingAssert.IsTrue(5000, () => testInst.ActiveThreadCount <= Environment.ProcessorCount, "4. testInst.ActiveThreadCount <= Environment.ProcessorCount");
            }
        }
예제 #20
0
        private void RunTestOnPool(DynamicThreadPool pool, int totalTaskCount, int taskSpinCount, int spawnThreadCount, int spawnSpinTime, bool spawnFromPool)
        {
            Random rndGenerator = new Random();

            int executedTaskCounter = 0;
            int completedTaskCount  = 0;


            Action taskAction = null;

            taskAction = () =>
            {
                int curTaskSpinCount = taskSpinCount;
                lock (rndGenerator)
                    curTaskSpinCount = rndGenerator.Next(taskSpinCount);

                Thread.SpinWait(curTaskSpinCount);

                if (spawnFromPool)
                {
                    if (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount)
                    {
                        pool.Run(taskAction);
                    }
                }

                Interlocked.Increment(ref completedTaskCount);
            };

            Barrier bar = new Barrier(spawnThreadCount + 1);

            Random spawnRndGenerator = new Random();

            Thread[]    spawnThreads = new Thread[spawnThreadCount];
            ThreadStart spawnAction  = () =>
            {
                bar.SignalAndWait();
                while (Interlocked.Increment(ref executedTaskCounter) <= totalTaskCount)
                {
                    pool.Run(taskAction);

                    int curSpawnSpinCount = spawnSpinTime;
                    lock (spawnRndGenerator)
                        curSpawnSpinCount = spawnRndGenerator.Next(spawnSpinTime);

                    Thread.SpinWait(curSpawnSpinCount);
                }
            };


            for (int i = 0; i < spawnThreads.Length; i++)
            {
                spawnThreads[i] = new Thread(spawnAction);
            }

            for (int i = 0; i < spawnThreads.Length; i++)
            {
                spawnThreads[i].Start();
            }

            bar.SignalAndWait();

            TimingAssert.AreEqual(60 * 1000, totalTaskCount, () => Volatile.Read(ref completedTaskCount));
        }
예제 #21
0
 public BackgroundModule(QueueConfiguration queueConfiguration)
 {
     _tasks      = new List <SearchTask>();
     _threadPool = new DynamicThreadPool(1, queueConfiguration.ProcessotCount, queueConfiguration.MaxSizeQueue,
                                         "BackgroundModule");
 }