]> hydra-www.ietfng.org Git - acmetensortoys-esp-lua_core/commitdiff
tq bugfixes (and API change)
authorNathaniel Wesley Filardo <nwf@cs.jhu.edu>
Sat, 29 Jul 2017 19:32:45 +0000 (15:32 -0400)
committerNathaniel Wesley Filardo <nwf@cs.jhu.edu>
Sun, 30 Jul 2017 07:06:22 +0000 (03:06 -0400)
- not all lapsed time should be credited to the head node
- needs to reset the time base (_tst) in all cases
- always return the object for cancellation
- defend against time going backwards (just in case)

While here, rework to simplify, simplify API, and add comments

tq/tq.lua

index c9ef8ba6e38bc4327ed59f6704413692c7bf1cba..55c5e354a93b19947762ffdb26e1e4d871b0849f 100644 (file)
--- a/tq/tq.lua
+++ b/tq/tq.lua
@@ -1,15 +1,15 @@
 -- DEPENDS: tmr [only by default]
-local fire, doarm
-function fire(self)
-  local cbt = {}
+local function fire(self)
   local entryt = self:now()
-  local lapsed = (entryt - self._tst)/1000
+  local lapsed = (entryt > self._tst) and (entryt - self._tst)/1000 or 0
   if #self._q > 0 and lapsed < self._q[1].t then
     -- premature fire?  adjust and rearm
     self._q[1].t = self._q[1].t - lapsed
-    doarm(self, self._q[1].t)
+    self._tst = entryt
+    self:arm(self._q[1].t, entryt)
     return
   end
+  local cbt = {}
   while #self._q > 0 and self._q[1].t <= lapsed do
     -- collect events in the past into cbt
     local cbs = table.remove(self._q,1)
@@ -19,28 +19,44 @@ function fire(self)
   if #self._q > 0 then
     -- leftover events: credit excess lapsed time and rearm
     self._q[1].t = self._q[1].t - lapsed
-    doarm(self, self._q[1].t)
+    self._tst = entryt
+    self:arm(self._q[1].t, entryt)
   end
   -- run all collected callbacks, having adjusted queue
   local k, cbs, v
   for k,cbs in ipairs(cbt) do for k,v in ipairs(cbs) do v() end end
 end
-function doarm(self,when) self:arm(function() fire(self) end, when); self._tst = self:now() end
 local function queue(self,when,what,...)
-  if #self._q > 0 then
-    local lapsed = (self:now() - self._tst)/1000
-    self._q[1].t = self._q[1].t - lapsed
-  end
-  local ix = 0; local tleft = when
-  while (ix < #self._q) do
-    if (tleft < self._q[ix+1].t) then break end
+  local entryt = self:now()
+  local lapsed = (entryt > self._tst) and (entryt - self._tst)/1000 or 0
+  self._tst = entryt
+   -- scan upwards for insertion position
+  local ix = 0
+  local tleft = when
+  while ix < #self._q do
+    local qi = self._q[ix+1]
+    -- credit lapsed time, if any
+    if     (lapsed > qi.t) then lapsed = lapsed - qi.t ; qi.t = 0 -- entirely covers
+    elseif (lapsed > 0   ) then qi.t = qi.t - lapsed ; lapsed = 0 -- partially covers
+    end
+    -- see if this bucket extends far enough in time
+    -- (now that we have subtracted any lapsed time)
+    if (tleft < qi.t) then break end
     ix = ix + 1; tleft = tleft - self._q[ix].t
   end
+  -- invariant: lapsed == 0
+  -- create queue element
   local warg = {...}; local nwarg = select('#',...)
-  local wfn = function () return what(unpack(warg,1,nwarg)) end
-  if ix == 0 then doarm(self,when)
-  elseif tleft == 0 then table.insert(self._q[ix],wfn); return
+  local wfn = function () what(unpack(warg,1,nwarg)) end
+  if ix == 0 then
+    -- we're going at the head of the queue, so set the new firing time
+    self:arm(when, entryt)
+  elseif tleft == 0 then
+    -- we're going in an existing bucket that isn't the first
+    table.insert(self._q[ix],wfn)
+    return wfn
   end
+  -- create a new bucket
   table.insert(self._q,ix+1,{["t"] = tleft, [1] = wfn})
   if ix+1 < #self._q then
     self._q[ix+2].t = self._q[ix+2].t - tleft
@@ -53,9 +69,11 @@ local function dequeue(self,what)
     if w == what then table.remove(v,k) end
   end end
 end
-local function defl_arm(self,fn,t) tmr.alarm(self.tmr, t, tmr.ALARM_SINGLE, fn) end
-local function defl_now(_) return tmr.now() end
+local function defl_arm(self,t)
+  tmr.alarm(self.tmr, t, tmr.ALARM_SINGLE, function() self:fire() end)
+end
 return function(tmrix) return {
   _q = {}, _tst = 0,
-  ["arm"] = defl_arm, ["now"] = defl_now, ["tmr"] = tmrix, ["queue"] = queue, ["dequeue"] = dequeue
+  ["fire"] = fire, ["arm"] = defl_arm, ["now"] = tmr and tmr.now,
+  ["tmr"] = tmrix, ["queue"] = queue, ["dequeue"] = dequeue
 } end