예제 #1
0
        /// <summary>
        ///     Checks out a segment, creating more if the pool is empty.
        /// </summary>
        /// <returns>a BufferSegment object from the pool</returns>
        public BufferSegment CheckOut()
        {
            BufferSegment segment;

            if (!m_availableSegments.TryDequeue(out segment))
            {
                lock (m_buffers)
                {
                    while (!m_availableSegments.TryDequeue(out segment))
                    {
                        CreateBuffer();
                    }
                }
            }

            // set initial usage to 1
            segment.Uses = 1;

            //Debug.WriteLineIf(UsedSegmentCount != lastValue, string.Format("Used:{0} Last:{1} Stack:{2}", UsedSegmentCount, lastValue, new StackTrace()));
            lastValue = UsedSegmentCount;
#if DEBUG
            m_segmentsInUse.TryAdd(segment.Number, segment);
            segment.LastUserTrace = new StackTrace().ToString();
            segment.LastUsage     = DateTime.Now;
#endif
            return(segment);
        }
예제 #2
0
#pragma warning disable 0693
        /// <summary>
        /// Removes an object from the queue.
        /// </summary>
        /// <returns>An object from the queue or a new object if none were in the queue.</returns>

        public T Obtain()
        {
            if (m_isBalanced)
            {
                Interlocked.Increment(ref m_obtainedReferenceCount);
            }

DequeueObj:
            {
                object obj;
                if (!m_queue.TryDequeue(out obj))
                {
                    return(m_createObj());
                }

                if (obj is WeakReference)
                {
                    var robj = ((WeakReference)obj).Target;
                    if (robj != null)
                    {
                        return(robj as T);
                    }

                    goto DequeueObj;
                }

                Interlocked.Decrement(ref m_hardReferences);
                return(obj as T);
            }
        }
예제 #3
0
        public void New_TryDequeue_TryEnqueue_x50_TryDequeue_x50_TryDequeue_Count()
        {
            int value;
            var q = new LockFreeQueue <int>();

            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);

            for (int i = 0; i < 50; ++i)
            {
                q.TryEnqueue(100 - i);
            }
            Assert.AreEqual(50, q.Count);

            for (int i = 0; i < 50; ++i)
            {
                q.TryDequeue(out value);
                Assert.AreEqual(100 - i, value);
            }
            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);
        }
예제 #4
0
        public void New_TryDequeue_TryDequeue_Count()
        {
            int value;
            var q = new LockFreeQueue<int>();
            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);
        }
예제 #5
0
        public void New_TryDequeue_TryDequeue_Count()
        {
            int value;
            var q = new LockFreeQueue <int>();

            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);
        }
예제 #6
0
        /// <summary>
        /// To avoid too much context switching, we try to processing several commands.
        /// But this thread cannot execute during too much time.
        /// </summary>
        void ProcessAllCommands()
        {
            while (_isRunning)
            {
                //---- Get the next command
                ICommand command;

                if (!_commands.TryDequeue(out command))
                {
                    return; // No more commands
                }

                Interlocked.Decrement(ref _commandsCount);

                //---- Execute the command
                try
                {
                    command.Execute();
                }
                catch (Exception ex)
                {
                    _log.Error("", ex);
                }

                // Statistics
                Interlocked.Increment(ref _totalExecutedCommands);
            }
        }
        private void removeLq_Action(int item, ParallelLoopState ls)
        {
            int r;

            lq.TryDequeue(out r);
            lqDestination.Enqueue(r);
        }
예제 #8
0
        public void DequeueTest_OneThread()
        {
            int value = 0;

            int[] values = new int[this.m_threadCount * this.m_dataCount];
            LockFreeQueue <int> queue = new LockFreeQueue <int>();

            Assert.IsFalse(queue.TryDequeue(out value));
            this.PrepareQueueData(queue, this.m_threadCount * this.m_dataCount);

            for (int j = 0; j < this.m_threadCount * this.m_dataCount; j++)
            {
                if (queue.TryDequeue(out value))
                {
                    Assert.AreNotEqual(0, values[j] = value);
                }
            }

            Assert.AreEqual(0, queue.Count);
        }
예제 #9
0
        /// <summary>
        ///     Checks out a segment, creating more if the pool is empty.
        /// </summary>
        /// <returns>a BufferSegment object from the pool</returns>
        public BufferSegment CheckOut()
        {
            BufferSegment segment;

            if (!m_availableSegments.TryDequeue(out segment))
            {
                lock (m_buffers)
                {
                    while (!m_availableSegments.TryDequeue(out segment))
                    {
                        CreateBuffer();
                    }
                }
            }

            // this doubles up with what CheckIn() looks for, but no harm in that, really.
            if (segment.Uses > 1)
            {
#if DEBUG
                log.Error(
                    "Checked out segment (Size: {0}, Number: {1}, Uses: {6}) that is already in use! Queue contains: {2}, Buffer amount: {3} Last usage : {4} StackTrace : {5}",
                    segment.Length, segment.Number, m_availableSegments.Count, m_buffers.Count, segment.LastUserTrace, new StackTrace().ToString(), segment.Uses);
#else
                log.Error(
                    "Checked out segment (Size: {0}, Number: {1}, Uses: {5}) that is already in use! Queue contains: {2}, Buffer amount: {3}, Stack Trace : {4}",
                    segment.Length, segment.Number, m_availableSegments.Count, m_buffers.Count, new StackTrace().ToString(), segment.Uses);
#endif
            }

            // set initial usage to 1
            segment.Uses = 1;

            //Debug.WriteLineIf(UsedSegmentCount != lastValue, string.Format("Used:{0} Last:{1} Stack:{2}", UsedSegmentCount, lastValue, new StackTrace()));
            lastValue = UsedSegmentCount;
#if DEBUG
            m_segmentsInUse.TryAdd(segment.Number, segment);
            segment.LastUserTrace = new StackTrace().ToString();
            segment.LastUsage     = DateTime.Now;
#endif
            return(segment);
        }
예제 #10
0
        //
        //编写测试时,还可使用以下属性:
        //
        //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //使用 TestInitialize 在运行每个测试前先运行代码
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //使用 TestCleanup 在运行完每个测试后运行代码
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///TryDequeue 的测试
        ///</summary>
        public void TryDequeueTestHelper <ValueT>()
        {
            LockFreeQueue <ValueT> target = new LockFreeQueue <ValueT>(); // TODO: 初始化为适当的值
            ValueT outItemT         = default(ValueT);                    // TODO: 初始化为适当的值
            ValueT outItemTExpected = default(ValueT);                    // TODO: 初始化为适当的值
            bool   expected         = false;                              // TODO: 初始化为适当的值
            bool   actual;

            actual = target.TryDequeue(out outItemT);
            Assert.AreEqual(outItemTExpected, outItemT);
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("验证此测试方法的正确性。");
        }
예제 #11
0
        public void AllTest()
        {
            int seed = 0;

            Thread[]            producerThreads = new Thread[this.m_threadCount];
            Thread[]            consumerThreads = new Thread[this.m_threadCount];
            LockFreeQueue <int> queue           = new LockFreeQueue <int>();

            for (int i = 0; i < this.m_threadCount; i++)
            {
                producerThreads[i] = new Thread(() => {
                    for (int j = 0; j < this.m_dataCount; j++)
                    {
                        queue.Enqueue(Interlocked.Increment(ref seed));
                    }
                });
            }
            for (int i = 0; i < this.m_threadCount; i++)
            {
                consumerThreads[i] = new Thread(() => {
                    int value = 0;
                    for (int j = 0; j < this.m_dataCount;)
                    {
                        if (queue.TryDequeue(out value))
                        {
                            Assert.AreNotEqual(0, value);

                            j++;
                        }
                        else
                        {
                            Thread.Sleep(1);
                        }
                    }
                });
            }

            for (int i = 0; i < this.m_threadCount; i++)
            {
                producerThreads[i].Start();
                consumerThreads[i].Start();
            }

            for (int i = 0; i < this.m_threadCount; i++)
            {
                producerThreads[i].Join();
                consumerThreads[i].Join();
            }

            Assert.AreEqual(0, queue.Count);
        }
예제 #12
0
        /* ***************************************************** */
        /* Protected Methods */
        /* ***************************************************** */


        protected void SelectLoop()
        {
            Thread.CurrentThread.Name = "tcp_select_thread";

            //No one can see this except this thread, so there is no
            //need for thread synchronization
            SocketState ss = new SocketState(this);

            ss.TAA = _ta_auth;

            if (ProtocolLog.Monitor.Enabled)
            {
                // log every 5 seconds.
                ActionQueue.Enqueue(new LogAction(new TimeSpan(0, 0, 0, 0, 5000), ActionQueue));
            }
            //Start the select action:
            ActionQueue.Enqueue(new SelectAction(this));
            bool got_action = false;

            while (ss.Run)
            {
                SocketStateAction a = ActionQueue.TryDequeue(out got_action);
                if (got_action)
                {
                    a.Start(ss);
                }
            }
            ShutdownAction sda = new ShutdownAction(this);

            sda.Start(ss);
            //Empty the queue to remove references to old objects
            do
            {
                ActionQueue.TryDequeue(out got_action);
            } while(got_action);
        }
예제 #13
0
        public void DequeueTest_MultipleThread()
        {
            Thread[]            threads = new Thread[this.m_threadCount];
            ICollection <int>[] values  = new ICollection <int> [this.m_threadCount];
            LockFreeQueue <int> queue   = new LockFreeQueue <int>();

            this.PrepareQueueData(queue, this.m_threadCount * this.m_dataCount);

            for (int i = 0; i < this.m_threadCount; i++)
            {
                values[i] = new List <int>(this.m_dataCount);

                threads[i] = new Thread((state) => {
                    int value = 0;
                    int index = (int)state;

                    for (int j = 0; j < this.m_dataCount; j++)
                    {
                        Assert.IsTrue(queue.TryDequeue(out value));
                        Assert.AreNotEqual(0, value);

                        values[index].Add(value);
                    }
                });
            }

            for (int i = 0; i < this.m_threadCount; i++)
            {
                threads[i].Start(i);
            }

            for (int i = 0; i < this.m_threadCount; i++)
            {
                threads[i].Join();
            }

            Assert.AreEqual(0, queue.Count);
            for (int i = 0; i < this.m_threadCount; i++)
            {
                Assert.AreEqual(this.m_dataCount, values[i].Count);
            }
            for (int i = 0; i < this.m_threadCount; i++)
            {
                Assert.AreEqual(this.m_dataCount, values[i].Distinct().Count());
            }
        }
예제 #14
0
        /// <summary>
        /// To avoid too much context switching, we try to processing several commands.
        /// But this thread cannot execute during too much time.
        /// </summary>
        private void ProcessAllCommands()
        {
            while (_isRunning)
            {
                //---- Get the next command
                ICommand command;

                if (!_commands.TryDequeue(out command))
                {
                    return;                     // No more commands
                }
                Interlocked.Decrement(ref _commandsCount);

                //---- Execute the command
                try
                {
                    command.Execute();
                }

                catch (Exception exception)
                {
                    ExceptionsHandler.Handle(exception);
                    //Console.WriteLine(exception.Message);
                }

                // Statistics
                Interlocked.Increment(ref _totalExecutedCommands);

                /*
                 *
                 *                              // Process commands since more than 20 ms, allows context switching
                 *                              if (HighResClock.TicksToMs(HighResClock.NowTicks - ticks) > ThreadHelper.ThreadMaxExecutionTime)
                 *                              {
                 *                                      ThreadHelper.StallThread();
                 *                                      return;
                 *                              }*/
            }
        }
예제 #15
0
        private void Tick()
        {
            if (!Running)
            {
                return;
            }

            try
            {
                if (Interlocked.CompareExchange(ref m_currentThreadId, Thread.CurrentThread.ManagedThreadId, 0) == 0)
                {
                    long timerStart = m_queueTimer.ElapsedMilliseconds;
                    var  updateDt   = (int)(timerStart - m_lastUpdate);
                    m_lastUpdate = (int)timerStart;

                    // do stuff here

                    // process timer entries
                    foreach (var timer in m_timers)
                    {
                        if (!timer.IsRunning)
                        {
                            RemoveTimer(timer);
                            continue;
                        }

                        try
                        {
                            timer.Update(updateDt);
                        }
                        catch (Exception ex)
                        {
                            logger.ErrorException(string.Format("Failed to update {0}", timer), ex);
                        }

                        if (!timer.IsRunning)
                        {
                            RemoveTimer(timer);
                        }

                        if (!Running)
                        {
                            Interlocked.Exchange(ref m_currentThreadId, 0);
                            return;
                        }
                    }

                    Action msg;
                    while (m_messageQueue.TryDequeue(out msg))
                    {
                        try
                        {
                            msg();
                        }
                        catch (Exception ex)
                        {
                            logger.ErrorException(string.Format("Failed to execute message {0}", msg), ex);
                        }

                        if (!Running)
                        {
                            Interlocked.Exchange(ref m_currentThreadId, 0);
                            return;
                        }
                    }

                    OnTick();

                    Interlocked.Exchange(ref m_currentThreadId, 0);

                    // get the end time
                    long timerStop = m_queueTimer.ElapsedMilliseconds;

                    bool updateLagged    = timerStop - timerStart > UpdateInterval;
                    long callbackTimeout = updateLagged ? 0 : ((timerStart + UpdateInterval) - timerStop);

                    Interlocked.Exchange(ref m_currentThreadId, 0);

                    if (updateLagged)
                    {
                        logger.Debug("TaskPool '{0}' update lagged ({1}ms)", Name, timerStop - timerStart);
                    }

                    if (Running)
                    {
                        // re-register the Update-callback
                        m_updateTask = Task.Factory.StartNewDelayed((int)callbackTimeout, Tick);
                    }
                }
                else
                {
                    Debug.WriteLine("");
                }
            }
            catch (Exception ex)
            {
                logger.FatalException(string.Format("Failed to run TaskQueue callback for \"{0}\"", Name), ex);
            }
        }
예제 #16
0
        public void New_TryEnqueue_x50_TryDequeue_x50_TryDequeue_Count()
        {
            int value;
            var q = new LockFreeQueue<int>();
            Assert.AreEqual(0, q.Count);

            for(int i = 0; i < 50; ++i) {
                q.TryEnqueue(100 - i);
            }
            Assert.AreEqual(50, q.Count);

            for(int i = 0; i < 50; ++i) {
                q.TryDequeue(out value);
                Assert.AreEqual(100 - i, value);
            }
            Assert.AreEqual(0, q.Count);

            q.TryDequeue(out value);
            Assert.AreEqual(0, q.Count);
        }
예제 #17
0
파일: Area.cs 프로젝트: Mixi59/Stump
        private void UpdateCallback(object state)
        {
            if ((IsDisposed || !IsRunning) ||
                (Interlocked.CompareExchange(ref m_currentThreadId, Thread.CurrentThread.ManagedThreadId, 0) != 0))
            {
                logger.Info($"Area {this} exit callback since it's disposed");
                return;
            }

            var  updateStart         = DateTime.Now;
            var  updateDelta         = (int)((updateStart - m_lastUpdateTime).TotalMilliseconds);
            long messageProcessTime  = 0;
            long timerProcessingTime = 0;
            var  timerProcessed      = 0;
            var  processedMessages   = new List <BenchmarkEntry>();

            try
            {
                var      sw = Stopwatch.StartNew();
                IMessage msg;
                while (m_messageQueue.TryDequeue(out msg))
                {
                    var swMsg = Stopwatch.StartNew();
                    try
                    {
                        msg.Execute();
                        swMsg.Stop();
                        if (BenchmarkManager.Enable && swMsg.Elapsed.TotalMilliseconds > 50)
                        {
                            processedMessages.Add(BenchmarkEntry.Create(msg.ToString(), swMsg.Elapsed, "area", Id));
                        }
                    }
                    catch (Exception ex)
                    {
                        swMsg.Stop();
                        logger.Error("Exception raised when processing Message in {0} : {1}.", this, ex);
                        if (BenchmarkManager.Enable)
                        {
                            processedMessages.Add(BenchmarkEntry.Create(msg.ToString(), swMsg.Elapsed, "area", Id, "exception", ex));
                        }
                    }
                }
                sw.Stop();
                messageProcessTime = sw.ElapsedMilliseconds;

                m_isUpdating = true;

                foreach (var timer in m_pausedTimers.Where(timer => timer.Enabled))
                {
                    m_timers.Push(timer);
                }

                sw = Stopwatch.StartNew();
                TimedTimerEntry peek;
                while ((peek = m_timers.Peek()) != null && peek.NextTick <= DateTime.Now)
                {
                    var timer = m_timers.Pop();

                    if (!timer.Enabled)
                    {
                        if (!timer.IsDisposed)
                        {
                            m_pausedTimers.Add(timer);
                        }
                    }
                    else
                    {
                        try
                        {
                            var swMsg = Stopwatch.StartNew();
                            timer.Trigger();
                            swMsg.Stop();

                            if (BenchmarkManager.Enable && swMsg.Elapsed.TotalMilliseconds > 20)
                            {
                                processedMessages.Add(BenchmarkEntry.Create(timer.ToString(), swMsg.Elapsed, "area", Id));
                            }

                            if (timer.Enabled)
                            {
                                m_timers.Push(timer);
                            }

                            timerProcessed++;
                        }
                        catch (Exception ex)
                        {
                            logger.Error("Exception raised when processing TimerEntry in {0} : {1}.", this, ex);
                        }
                    }
                }
                sw.Stop();
                timerProcessingTime = sw.ElapsedMilliseconds;
            }
            finally
            {
                try
                {
                    // we updated the map, so set our last update time to now
                    m_lastUpdateTime = updateStart;
                    TickCount++;
                    m_isUpdating = false;

                    // get the time, now that we've finished our update callback
                    var updateEnd      = DateTime.Now;
                    var newUpdateDelta = updateEnd - updateStart;

                    // weigh old update-time 9 times and new update-time once
                    AverageUpdateTime = ((AverageUpdateTime * 9) + (float)(newUpdateDelta).TotalMilliseconds) / 10;

                    // make sure to unset the ID *before* enqueuing the task in the ThreadPool again
                    Interlocked.Exchange(ref m_currentThreadId, 0);
                    var callbackTimeout = (int)(m_updateDelay - newUpdateDelta.TotalMilliseconds);
                    if (callbackTimeout < 0)
                    {
                        // even if we are in a hurry: For the sake of load-balance we have to give control back to the ThreadPool
                        callbackTimeout = 0;
                        logger.Debug("Area '{0}' update lagged ({1}ms) (msg:{2}ms, timers:{3}ms, timerProc:{4}/{5})",
                                     this, (int)newUpdateDelta.TotalMilliseconds, messageProcessTime, timerProcessingTime, timerProcessed, m_timers.Count);
                        foreach (var msg in processedMessages.OrderByDescending(x => x.Timestamp).Take(15))
                        {
                            logger.Debug(msg);
                        }

                        BenchmarkManager.Instance.AddRange(processedMessages.OrderByDescending(x => x.Timestamp).Take(15));
                    }

                    if (!m_running)
                    {
                        m_stoppedAsync.Set();
                    }
                    else
                    {
                        m_currentTask = Task.Factory.StartNewDelayed(callbackTimeout, UpdateCallback, this);
                    }
                }
                catch (Exception ex)
                {
                    logger.Error("Area {0}. Could not recall callback !! Exception {1}", this, ex);
                }
            }
        }
예제 #18
0
        protected void ProcessCallback(object state)
        {
            if (!IsRunning)
            {
                return;
            }

            if (Interlocked.CompareExchange(ref m_currentThreadId, Thread.CurrentThread.ManagedThreadId, 0) != 0)
            {
                return;
            }
            long timerStart = 0;

            // get the time at the start of our task processing
            timerStart = m_queueTimer.ElapsedMilliseconds;
            var updateDt = (int)(timerStart - m_lastUpdate);

            m_lastUpdate = (int)timerStart;

            int msgCount    = 0;
            int timersCount = 0;
            var list        = new List <IMessage>();

            try
            {
                // process messages
                IMessage msg;
                while (m_messageQueue.TryDequeue(out msg))
                {
                    msgCount++;
                    list.Add(msg);
                    try
                    {
                        msg.Execute();
                    }
                    catch (Exception ex)
                    {
                        logger.Error("Failed to execute message {0} : {1}", msg, ex);
                    }

                    if (!IsRunning)
                    {
                        return;
                    }
                }

                foreach (var timer in m_pausedTimers.Where(timer => timer.Enabled))
                {
                    m_timers.Push(timer);
                }

                TimedTimerEntry peek;
                while ((peek = m_timers.Peek()) != null && peek.NextTick <= DateTime.Now)
                {
                    timersCount++;
                    var timer = m_timers.Pop();

                    if (!timer.Enabled)
                    {
                        if (!timer.IsDisposed)
                        {
                            m_pausedTimers.Add(timer);
                        }
                    }
                    else
                    {
                        try
                        {
                            timer.Trigger();

                            if (timer.Enabled)
                            {
                                m_timers.Push(timer);
                            }
                        }
                        catch (Exception ex)
                        {
                            logger.Error("Exception raised when processing TimerEntry {2} in {0} : {1}.", this, ex, timer);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error("Failed to run TaskQueue callback for \"{0}\" : {1}", Name, ex);
            }
            finally
            {
                // get the end time
                var timerStop = m_queueTimer.ElapsedMilliseconds;

                var updateLagged    = timerStop - timerStart > UpdateInterval;
                var callbackTimeout = updateLagged ? 0 : ((timerStart + UpdateInterval) - timerStop);

                Interlocked.Exchange(ref m_currentThreadId, 0);

                if (updateLagged)
                {
#if DEBUG
                    logger.Debug("TaskPool '{0}' update lagged ({1}ms) (msg:{2}, timers:{3}/{4})", Name, timerStop - timerStart, msgCount, timersCount, m_timers.Count);
                    var orderList = list.OrderByDescending(x =>
                    {
                        try
                        {
                            return(((dynamic)x).ElapsedTime);
                        }
                        catch
                        {
                            return(0);
                        }
                    }).ToList();
                    for (int i = 0; i < 10 && i < orderList.Count; i++)
                    {
                        logger.Debug("{0}", orderList[i]);
                    }
#endif
                }
                if (IsRunning)
                {
                    // re-register the Update-callback
                    m_updateTask = Task.Factory.StartNewDelayed((int)callbackTimeout, ProcessCallback, this);
                }
                else
                {
                    m_stoppedAsync.Set();
                }
            }
        }