Module timerwheel
Timer wheel implementation
Efficient timer for timeout related timers: fast insertion, deletion, and execution (all as O(1) implemented), but with lesser precision.
This module will not provide the timer/runloop itself. Use your own runloop and call wheel:step to check and execute timers.
Implementation: Consider a stack of rings, a timer beyond the current ring size is in the next ring (or beyond). Precision is based on a slot with a specific size.
The code explicitly avoids using pairs, ipairs and next to ensure JIT compilation when using LuaJIT
Functions
new (opts) | Creates a new timer wheel. |
wheel:cancel (id) | Cancels a timer. |
wheel:count () | Gets the number of timers. |
wheel:peek ([max_ahead]) | Looks up the next expiring timer. |
wheel:set (expire_in, cb, arg) | Sets a timer. |
wheel:step () | Checks and executes timers. |
Functions
- new (opts)
-
Creates a new timer wheel.
Parameters:
- opts the options table
- precision number the precision of the timer wheel in seconds (slot size), (default 0.050)
- ringsize
int
number of slots in each ring, defaults to 72000 (1
hour span, with
precision == 0.050
) (optional) - now
function
a function returning the curent time in seconds. Defaults
to
ngx.now
orluasocket.gettime
if available. (optional) - err_handler
function
a function to use as error handler in an xpcall when
executing the callback. The default will write the stacktrace to
stderr
. (optional)
Returns:
-
wheel
the timerwheel object
- opts the options table
- wheel:cancel (id)
-
Cancels a timer.
Parameters:
- id int the timer id to cancel
Returns:
-
boolean
true
if cancelled,false
if not found - wheel:count ()
-
Gets the number of timers.
Returns:
-
int
number of timers
- wheel:peek ([max_ahead])
-
Looks up the next expiring timer.
Note: traverses the wheel, O(n) operation!
Parameters:
- max_ahead number maximum time (in seconds) to look ahead (optional)
Returns:
-
number
number of seconds until next timer expires (can be negative), or
'nil' if there is no timer from now to
max_ahead
Usage:
local t = wheel:peek(10) if t then print("next timer expires in ", t," seconds") else print("no timer scheduled for the next 10 seconds") end
- wheel:set (expire_in, cb, arg)
-
Sets a timer.
Parameters:
- expire_in number in how many seconds should the timer expire
- cb function callback function to execute upon expiring (NOTE: the callback will run within an xpcall)
- arg
parameter to be passed to
cb
when executing
Returns:
-
int
the id of the newly set timer
Usage:
local cb = function(arg) print("timer executed with: ", arg) --> "timer executed with: hello world" end local id = wheel:set(5, cb, "hello world") -- do stuff here, while regularly calling
wheel:step()
wheel:cancel(id) -- cancel the timer again - wheel:step ()
-
Checks and executes timers.
Call this function (at least) every
precision
seconds.Returns:
true