Mercurial > prosody-hg
comparison util/smqueue.lua @ 14198:73903352de86
util.smqueue: Refactor checkpoint logic and add tests
The previous checkpoint logic used recursion, and the code was more complex
than needed due to maintenance of the self._next_checkpoint field.
This switches to a loop, which should be a bit more efficient, partly because
there are fewer calls (although it was a tail call) and because table lookups
can now be cached between each execution.
_call_checkpoints() is now called unconditionally for every ack, which is
simpler though adds a function call, it should be more than balanced out by
the other changes.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Tue, 26 May 2026 15:36:36 +0100 |
| parents | 1e01b91cf94d |
| children |
comparison
equal
deleted
inserted
replaced
| 14197:3b26b8772fb1 | 14198:73903352de86 |
|---|---|
| 29 return nil, "pop" | 29 return nil, "pop" |
| 30 end | 30 end |
| 31 table.insert(acked, v); | 31 table.insert(acked, v); |
| 32 end | 32 end |
| 33 | 33 |
| 34 local c = self._next_checkpoint; | 34 self:_call_checkpoints(h); |
| 35 if c and h >= c then | 35 |
| 36 self:_call_checkpoints(h); | |
| 37 end | |
| 38 return acked | 36 return acked |
| 39 end | 37 end |
| 40 | 38 |
| 41 function smqueue:count_unacked() | 39 function smqueue:count_unacked() |
| 42 return self._head - self._tail | 40 return self._head - self._tail |
| 66 return t | 64 return t |
| 67 end | 65 end |
| 68 | 66 |
| 69 function smqueue:add_checkpoint(cb, ud) | 67 function smqueue:add_checkpoint(cb, ud) |
| 70 table.insert(self._checkpoints, { self._head; cb; ud }); | 68 table.insert(self._checkpoints, { self._head; cb; ud }); |
| 71 if not self._next_checkpoint then | |
| 72 self._next_checkpoint = self._head; | |
| 73 end | |
| 74 end | 69 end |
| 75 | 70 |
| 76 function smqueue:_call_checkpoints(h) | 71 function smqueue:_call_checkpoints(h) |
| 77 local checkpoints = self._checkpoints; | 72 local checkpoints = self._checkpoints; |
| 73 local c = checkpoints[1]; | |
| 78 | 74 |
| 79 local c = table.remove(checkpoints, 1); | 75 while c and h >= c[1] do |
| 80 self._next_checkpoint = checkpoints[1] and checkpoints[1][1] or nil; | 76 table.remove(checkpoints, 1); |
| 81 | 77 local cb, ud = c[2], c[3]; |
| 82 local cb, ud = c[2], c[3]; | 78 cb(ud); |
| 83 cb(ud); | 79 c = checkpoints[1]; |
| 84 | |
| 85 if h >= self._next_checkpoint then | |
| 86 return self:_call_checkpoints(h) | |
| 87 end | 80 end |
| 88 end | 81 end |
| 89 | 82 |
| 90 local function freeze(q) | 83 local function freeze(q) |
| 91 return { head = q._head; tail = q._tail } | 84 return { head = q._head; tail = q._tail } |
