Feels like a bit of a pitfall to begin with: we used to turn timers off with delay 0, not that there is any reason not to interpret delay 0 as "call the timer as soon as possible" but it's not consistent with the old logic.
However, it also does not work properly: try this script:
local count = 0
local stime = 0
function timer()
count += 1
ll.SetLinkPrimitiveParamsFast(LINK_THIS, {PRIM_TEXT, tostring(count), vector(1, 1, 1), 1})
if count >= 100 then -- never reached at 0.0 delay, will be reached at 0.001
ll.OwnerSay(`finished in {os.clock()-stime} s`)
LLTimers:off(timer)
end
end
function LLEvents.touch_start() -- disable this event and the count reaches higher, but not 100
ll.OwnerSay(`current count = {count}`)
end
stime = os.clock()
-- set delay to 0.001 (or anything sub-server frame) to have functional
-- "call as soon as possible" rate
LLTimers:every(0.0, timer)
The count will never reach 100 and terminate in my tests, it's like the timer gets jammed. Using a delay of 0.001 (or anything > 0 but sub-frame) will achieve the expected "as soon as possible" timing. Also disabling the touch event lets the timer count higher (still not 100), so there's some dependency on the event system on the whole there.