From 1d02fac76e3a0c902e92807edc76a86de92cdee1 Mon Sep 17 00:00:00 2001 From: Daniel Yates Date: Wed, 8 May 2024 15:29:50 +0100 Subject: [PATCH] Allow direct sending while in a blocked state With the changes to support the concept of a blocked queue, there's a slight latency defect possible when CTL is in a state where its priorities consist solely of blocked queues. The direct submission checks in the Send functions eagerly return false in the case where the 'bQueueing' boolean is set, and force their data to be queued up for submission ~potentially up to 0.08s later. The problem is that this boolean is only ever cleared in the case where CTL has no data whatsoever left in any queue. This means that if CTL has only blocked (and as such, totally idle) queues the boolean remains set, and we force messages that could be perfectly sendable right away to instead be queued up unnecessarily. This attempts to resolve the issue as follows; - Firstly, we now clear the 'bQueueing' flag in the OnUpdate function if we enter a state where there's no data that can be *immediately* sent. This means that the flag is unset if we only consist of blocked queues. - The OnUpdate function restores the 'bQueueing' flag when transitioning back from a fully-blocked state to a sendable state. - The direct send checks have been split out to a new function and in addition to checking the state of 'bQueueing', now also check if a named queue exists within a certain priority bracket. If it does, then we do not directly send the message. The new check is required to deal with cases where a caller attempts to send a message on a specific queue while 'bQueueing' is false - as we don't want to directly send a message ahead of everything else in the queue that it's supposed to belong to. --- AceComm-3.0/ChatThrottleLib.lua | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/AceComm-3.0/ChatThrottleLib.lua b/AceComm-3.0/ChatThrottleLib.lua index 688d318..cf3c511 100644 --- a/AceComm-3.0/ChatThrottleLib.lua +++ b/AceComm-3.0/ChatThrottleLib.lua @@ -23,7 +23,7 @@ -- LICENSE: ChatThrottleLib is released into the Public Domain -- -local CTL_VERSION = 29 +local CTL_VERSION = 30 local _G = _G @@ -482,11 +482,15 @@ function ChatThrottleLib.OnUpdate(this,delay) if nSendablePrios == 0 then -- If we're completely out of data to send, disable queue processing. if nBlockedPrios == 0 then - self.bQueueing = false self.Frame:Hide() end + -- Allow directly sending messages again. In our current state we only + -- consist of either fully blocked queues, or have no queues at all. + self.bQueueing = false return + else + self.bQueueing = true end -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues @@ -523,6 +527,21 @@ function ChatThrottleLib:Enqueue(prioname, pipename, msg) self.bQueueing = true end +function ChatThrottleLib:IsDirectSendAllowed(prioName, queueName, nSize) + if self.bQueueing then + -- There's data sitting in sendable queues. Don't bypass them. + return false + elseif self.Prio[prioName].ByName[queueName] then + -- This data belongs to an existing and blocked pipe. Append to it. + return false + elseif nSize >= self:UpdateAvail() then + -- This data is too large to send off right away. + return false + else + return true + end +end + function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg) if not self or not prio or not prefix or not text or not self.Prio[prio] then error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2) @@ -538,9 +557,10 @@ function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, languag end nSize = nSize + self.MSG_OVERHEAD + queueName = queueName or prefix -- Check if there's room in the global available bandwidth gauge to send directly - if not self.bQueueing and nSize < self:UpdateAvail() then + if self:IsDirectSendAllowed(prio, queueName, nSize) then local sendResult = PerformSend(_G.SendChatMessage, text, chattype, language, destination) if not IsThrottledSendResult(sendResult) then @@ -571,15 +591,16 @@ function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, languag msg.callbackFn = callbackFn msg.callbackArg = callbackArg - self:Enqueue(prio, queueName or prefix, msg) + self:Enqueue(prio, queueName, msg) end local function SendAddonMessageInternal(self, sendFunction, prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg) local nSize = #text + self.MSG_OVERHEAD + queueName = queueName or prefix -- Check if there's room in the global available bandwidth gauge to send directly - if not self.bQueueing and nSize < self:UpdateAvail() then + if self:IsDirectSendAllowed(prio, queueName, nSize) then local sendResult = PerformSend(sendFunction, prefix, text, chattype, target) if not IsThrottledSendResult(sendResult) then @@ -610,7 +631,7 @@ local function SendAddonMessageInternal(self, sendFunction, prio, prefix, text, msg.callbackFn = callbackFn msg.callbackArg = callbackArg - self:Enqueue(prio, queueName or prefix, msg) + self:Enqueue(prio, queueName, msg) end