public void TestNoBlock()
        {
            BlockingThreadPool threadPool = new BlockingThreadPool(2, 2);
            MessageLog log = new MessageLog();

            for (int i = 0; i < TestIterationsCount; i++)
            {
                log.Clear();

                Assert.That(threadPool.Execute(() =>
                {
                    log.Log("task 1: started"); // T = 0
                    Thread.Sleep(200);
                    log.Log("task 1: finished"); // T = 200
                }, 100), Is.True);

                Thread.Sleep(50); // T = 50

                Assert.That(threadPool.Execute(() =>
                {
                    log.Log("task 2: started"); // T = 50
                    Thread.Sleep(200);
                    log.Log("task 2: finished"); // T = 250
                }, 100), Is.True);

                Thread.Sleep(50);
                log.Log("main: wait started"); // T = 100
                Thread.Sleep(200);
                log.Log("main: wait finished"); // T = 300

                Assert.That(log.GetLog(), Is.EqualTo(new string[]
                {
                    "task 1: started",
                    "task 2: started",
                    "main: wait started",
                    "task 1: finished",
                    "task 2: finished",
                    "main: wait finished"
                }));
            }

            Assert.That(threadPool.Stop(1000), Is.True);
        }
        private void Start()
        {
            VersionMessage outVersionMessage = CreateVersionMessage();
            WriteMessage(outVersionMessage);

            BitcoinMessage incVersionMessage = conn.ReadMessage();
            if (incVersionMessage.Command != VersionMessage.Command)
            {
                throw new BitcoinNetworkException("Remote endpoint did not send Version message.");
            }

            VersionMessage incVersionMessageParsed;
            using (BitcoinStreamReader reader = new BitcoinStreamReader(new MemoryStream(incVersionMessage.Payload)))
            {
                //todo: review and handle exceptions
                incVersionMessageParsed = VersionMessage.Read(reader);
            }

            //todo: check minimal peer protocol version

            WriteMessage(new VerAckMessage());

            BitcoinMessage incVerAckMessage = conn.ReadMessage();
            if (incVerAckMessage.Command != VerAckMessage.Command)
            {
                //todo: handle correctly
                throw new BitcoinNetworkException("Remote endpoint did not send VerAck message.");
            }

            peerInfo = new BitcoinPeerInfo(conn.RemoteEndPoint, incVersionMessageParsed);

            running = true;

            threadPool = new BlockingThreadPool(MessageProcessingThreadsCount, MessageProcessingTasksCount);

            listenerThread = new Thread(Listen);
            listenerThread.Name = "Endpoint Listener";
            listenerThread.IsBackground = true; //todo: ??? should it be background?
            listenerThread.Start();
        }
 public void WarmUp()
 {
     //the first thread creation can take considerable time
     Stopwatch sw = Stopwatch.StartNew();
     AutoResetEvent ev = new AutoResetEvent(false);
     BlockingThreadPool threadPool = new BlockingThreadPool(1, 1);
     Assume.That(threadPool.Execute(() => ev.Set(), 100), Is.True);
     ev.WaitOne();
     Assert.That(threadPool.Stop(1000), Is.True);
     Console.WriteLine("WarmUp: {0}ms", sw.ElapsedMilliseconds);
 }
 public void TestStopIdle()
 {
     BlockingThreadPool threadPool = new BlockingThreadPool(2, 2);
     Thread.Sleep(50);
     Assert.That(threadPool.Stop(50), Is.True);
     //check that Stop does not fail on a stopped pool
     Assert.That(threadPool.Stop(50), Is.True);
 }
        public void TestStopBusy()
        {
            MessageLog log = new MessageLog();

            for (int i = 0; i < TestIterationsCount; i++)
            {
                BlockingThreadPool threadPool = new BlockingThreadPool(3, 3);
                log.Clear();

                threadPool.Execute(() =>
                {
                    log.Log("task 1: started"); // T = 0
                    try
                    {
                        // finally block is required to ignore Thread.Interrupt and Thread.Abort
                    }
                    finally
                    {
                        Thread.Sleep(200);
                    }
                    log.Log("task 1: finished"); // T = 200
                }, 100);

                Thread.Sleep(50); // T = 50

                threadPool.Execute(() =>
                {
                    log.Log("task 2: started"); // T = 50
                    try
                    {
                        // finally block is required to ignore Thread.Interrupt and Thread.Abort
                    }
                    finally
                    {
                        Thread.Sleep(250);
                    }
                    log.Log("task 2: finished"); // T = 300
                }, 100);

                Thread.Sleep(50); // T = 50

                threadPool.Execute(() =>
                {
                    log.Log("task 3: started"); // T = 100
                    log.Log($"task 4 queued: {threadPool.Execute(() => { }, 300)}"); // T = 150
                    log.Log("task 3: finished"); // T = 150
                }, 100);

                Thread.Sleep(50); // T = 150

                Stopwatch sw = Stopwatch.StartNew();
                Assert.That(threadPool.Stop(100), Is.False); // T = 250
                Assert.That(sw.ElapsedMilliseconds, Is.GreaterThan(75).And.LessThan(125));

                sw.Restart();
                Assert.That(threadPool.Execute(() => { }, 100), Is.False);
                Assert.That(sw.ElapsedMilliseconds, Is.LessThan(25));

                sw.Restart();
                Assert.That(threadPool.Stop(100), Is.True); // T = 300
                Assert.That(sw.ElapsedMilliseconds, Is.GreaterThan(25).And.LessThan(75));

                //check that Stop does not fail on a stopped pool
                sw.Restart();
                Assert.That(threadPool.Stop(100), Is.True); // T = 300
                Assert.That(sw.ElapsedMilliseconds, Is.LessThan(25));

                Assert.That(log.GetLog(), Is.EqualTo(new string[]
                {
                    "task 1: started",
                    "task 2: started",
                    "task 3: started",
                    "task 4 queued: False",
                    "task 3: finished",
                    "task 1: finished",
                    "task 2: finished"
                }));
            }
        }
        public void TestPerformance()
        {
            const int poolThreadCount = 100;
            const int taskDelay = 10;

            BlockingThreadPool threadPool = new BlockingThreadPool(poolThreadCount, poolThreadCount*2);

            object lockObject = new object();

            long executedTasks = 0;
            long rejectedTasks = 0;
            long loopIterations = 0;
            int threadCount = 0;
            int maxThreadCount = 0;

            Action task = () =>
            {
                var newThreadCount = Interlocked.Increment(ref threadCount);
                lock (lockObject)
                {
                    if (newThreadCount > maxThreadCount)
                    {
                        maxThreadCount = newThreadCount;
                    }
                }

                Thread.Sleep(taskDelay);

                Interlocked.Increment(ref executedTasks);
                Interlocked.Decrement(ref threadCount);
            };

            Stopwatch sw = Stopwatch.StartNew();
            while (sw.ElapsedMilliseconds < 1000)
            {
                loopIterations++;
                for (int i = 0; i < 100; i++)
                {
                    if (!threadPool.Execute(task, taskDelay + 100))
                    {
                        rejectedTasks++;
                    }
                }
            }

            Assert.That(threadPool.Stop(1000), Is.True);

            Console.WriteLine("executedTasks:\t{0}", executedTasks);
            Console.WriteLine("rejectedTasks:\t{0}", rejectedTasks);
            Console.WriteLine("maxThreadCount:\t{0}", maxThreadCount);
            Console.WriteLine("loopIterations:\t{0}", loopIterations);

            Assert.That(maxThreadCount, Is.EqualTo(poolThreadCount));
            Assert.That(rejectedTasks, Is.EqualTo(0));
        }