private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue <LLQueItem> q, LLQueItem item) { // The idea.. is if the packet throttle queues are empty // and the client is under throttle for the type. Queue // it up directly. This basically short cuts having to // wait for the timer to fire to put things into the // output queue if ((q.Count == 0) && (throttle.UnderLimit())) { try { Monitor.Enter(this); throttle.AddBytes(item.Length); TotalThrottle.AddBytes(item.Length); SendQueue.Enqueue(item); } catch (Exception e) { // Probably a serialization exception m_log.WarnFormat("ThrottleCheck: {0}", e.ToString()); } finally { Monitor.Pulse(this); Monitor.Exit(this); } } else { q.Enqueue(item); } }
public void ProcessThrottle() { // I was considering this.. Will an event fire if the thread it's on is blocked? // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long // The General overhead of the UDP protocol gets sent to the queue un-throttled by this // so This'll pick up about around the right time. int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once. int throttleLoops = 0; // We're going to dequeue all of the saved up packets until // we've hit the throttle limit or there's no more packets to send lock (this) { // this variable will be true if there was work done in the last execution of the // loop, since each pass through the loop checks the queue length, we no longer // need the check on entering the loop bool qchanged = true; ResetCounters(); // m_log.Info("[THROTTLE]: Entering Throttle"); while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops) { qchanged = false; // We will break out of the loop if no work was accomplished throttleLoops++; //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up. if ((ResendOutgoingPacketQueue.Count > 0) && ResendThrottle.UnderLimit()) { LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); TotalThrottle.AddBytes(qpack.Length); ResendThrottle.AddBytes(qpack.Length); qchanged = true; } if ((LandOutgoingPacketQueue.Count > 0) && LandThrottle.UnderLimit()) { LLQueItem qpack = LandOutgoingPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); TotalThrottle.AddBytes(qpack.Length); LandThrottle.AddBytes(qpack.Length); qchanged = true; } if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit()) { LLQueItem qpack = WindOutgoingPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); TotalThrottle.AddBytes(qpack.Length); WindThrottle.AddBytes(qpack.Length); qchanged = true; } if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit()) { LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); TotalThrottle.AddBytes(qpack.Length); CloudThrottle.AddBytes(qpack.Length); qchanged = true; } if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit()) { LLQueItem qpack; if (TaskOutgoingPacketQueue.Count > 0) { qpack = TaskOutgoingPacketQueue.Dequeue(); SendQueue.PriorityEnqueue(qpack); } else { qpack = TaskLowpriorityPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); } TotalThrottle.AddBytes(qpack.Length); TaskThrottle.AddBytes(qpack.Length); qchanged = true; } if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit()) { LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); TotalThrottle.AddBytes(qpack.Length); TextureThrottle.AddBytes(qpack.Length); qchanged = true; } if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit()) { LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue(); SendQueue.Enqueue(qpack); TotalThrottle.AddBytes(qpack.Length); AssetThrottle.AddBytes(qpack.Length); qchanged = true; } } // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets"); } }