Software / code / prosody
Comparison
net/server_epoll.lua @ 10985:758ce12586de
net.server_epoll: Optimize away table allocation for timer objects
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Mon, 29 Jun 2020 20:23:59 +0200 |
| parent | 10984:69ed4764edda |
| child | 10987:62355b801772 |
comparison
equal
deleted
inserted
replaced
| 10984:69ed4764edda | 10985:758ce12586de |
|---|---|
| 84 -- Timer and scheduling -- | 84 -- Timer and scheduling -- |
| 85 | 85 |
| 86 local timers = indexedbheap.create(); | 86 local timers = indexedbheap.create(); |
| 87 | 87 |
| 88 local function noop() end | 88 local function noop() end |
| 89 local function closetimer(t) | 89 local function closetimer(id) |
| 90 t[1] = noop; | 90 timers:remove(id); |
| 91 timers:remove(t.id); | 91 end |
| 92 end | 92 |
| 93 | 93 local function reschedule(id, time) |
| 94 local function reschedule(t, time) | |
| 95 time = monotonic() + time; | 94 time = monotonic() + time; |
| 96 timers:reprioritize(t.id, time); | 95 timers:reprioritize(id, time); |
| 97 end | 96 end |
| 98 | 97 |
| 99 -- Add relative timer | 98 -- Add relative timer |
| 100 local function addtimer(timeout, f, param) | 99 local function addtimer(timeout, f, param) |
| 101 local time = monotonic() + timeout; | 100 local time = monotonic() + timeout; |
| 102 local timer = { f, param, close = closetimer, reschedule = reschedule, id = nil }; | 101 if param ~= nil then |
| 103 timer.id = timers:insert(timer, time); | 102 local timer_callback = f |
| 104 return timer; | 103 function f(current_time, timer_id) |
| 104 local t = timer_callback(current_time, timer_id, param) | |
| 105 return t; | |
| 106 end | |
| 107 end | |
| 108 local id = timers:insert(f, time); | |
| 109 return id; | |
| 105 end | 110 end |
| 106 | 111 |
| 107 -- Run callbacks of expired timers | 112 -- Run callbacks of expired timers |
| 108 -- Return time until next timeout | 113 -- Return time until next timeout |
| 109 local function runtimers(next_delay, min_wait) | 114 local function runtimers(next_delay, min_wait) |
| 116 if peek > elapsed then | 121 if peek > elapsed then |
| 117 next_delay = peek - elapsed; | 122 next_delay = peek - elapsed; |
| 118 break; | 123 break; |
| 119 end | 124 end |
| 120 | 125 |
| 121 local _, timer = timers:pop(); | 126 local _, timer, id = timers:pop(); |
| 122 local ok, ret = pcall(timer[1], now, timer, timer[2]); | 127 local ok, ret = pcall(timer, now, id); |
| 123 if ok and type(ret) == "number" then | 128 if ok and type(ret) == "number" then |
| 124 local next_time = elapsed+ret; | 129 local next_time = elapsed+ret; |
| 125 timers:insert(timer, next_time); | 130 timers:insert(timer, next_time); |
| 126 end | 131 end |
| 127 | 132 |
| 257 | 262 |
| 258 -- Timeout for detecting dead or idle sockets | 263 -- Timeout for detecting dead or idle sockets |
| 259 function interface:setreadtimeout(t) | 264 function interface:setreadtimeout(t) |
| 260 if t == false then | 265 if t == false then |
| 261 if self._readtimeout then | 266 if self._readtimeout then |
| 262 self._readtimeout:close(); | 267 closetimer(self._readtimeout); |
| 263 self._readtimeout = nil; | 268 self._readtimeout = nil; |
| 264 end | 269 end |
| 265 return | 270 return |
| 266 end | 271 end |
| 267 t = t or cfg.read_timeout; | 272 t = t or cfg.read_timeout; |
| 268 if self._readtimeout then | 273 if self._readtimeout then |
| 269 self._readtimeout:reschedule(t); | 274 reschedule(self._readtimeout, t); |
| 270 else | 275 else |
| 271 self._readtimeout = addtimer(t, function () | 276 self._readtimeout = addtimer(t, function () |
| 272 if self:on("readtimeout") then | 277 if self:on("readtimeout") then |
| 273 self:noise("Read timeout handled"); | 278 self:noise("Read timeout handled"); |
| 274 return cfg.read_timeout; | 279 return cfg.read_timeout; |
| 283 | 288 |
| 284 -- Timeout for detecting dead sockets | 289 -- Timeout for detecting dead sockets |
| 285 function interface:setwritetimeout(t) | 290 function interface:setwritetimeout(t) |
| 286 if t == false then | 291 if t == false then |
| 287 if self._writetimeout then | 292 if self._writetimeout then |
| 288 self._writetimeout:close(); | 293 closetimer(self._writetimeout); |
| 289 self._writetimeout = nil; | 294 self._writetimeout = nil; |
| 290 end | 295 end |
| 291 return | 296 return |
| 292 end | 297 end |
| 293 t = t or cfg.send_timeout; | 298 t = t or cfg.send_timeout; |
| 294 if self._writetimeout then | 299 if self._writetimeout then |
| 295 self._writetimeout:reschedule(t); | 300 reschedule(self._writetimeout, t); |
| 296 else | 301 else |
| 297 self._writetimeout = addtimer(t, function () | 302 self._writetimeout = addtimer(t, function () |
| 298 self:noise("Write timeout"); | 303 self:noise("Write timeout"); |
| 299 self:on("disconnect", self._connected and "write timeout" or "connection timeout"); | 304 self:on("disconnect", self._connected and "write timeout" or "connection timeout"); |
| 300 self:destroy(); | 305 self:destroy(); |
| 661 | 666 |
| 662 -- Pause connection for some time | 667 -- Pause connection for some time |
| 663 function interface:pausefor(t) | 668 function interface:pausefor(t) |
| 664 self:noise("Pause for %fs", t); | 669 self:noise("Pause for %fs", t); |
| 665 if self._pausefor then | 670 if self._pausefor then |
| 666 self._pausefor:close(); | 671 closetimer(self._pausefor); |
| 672 self._pausefor = nil; | |
| 667 end | 673 end |
| 668 if t == false then return; end | 674 if t == false then return; end |
| 669 self:set(false); | 675 self:set(false); |
| 670 self._pausefor = addtimer(t, function () | 676 self._pausefor = addtimer(t, function () |
| 671 self._pausefor = nil; | 677 self._pausefor = nil; |