/// <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); }
#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); } }
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); }
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); }
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); }
/// <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); }
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); }
/// <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); }
// //编写测试时,还可使用以下属性: // //使用 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("验证此测试方法的正确性。"); }
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); }
/* ***************************************************** */ /* 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); }
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()); } }
/// <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; * }*/ } }
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); } }
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); }
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); } } }
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(); } } }