gears.timer: Add simpler ways to start timers

This adds gears.timer.start(timeout, callback) that creates a timer object and
connects a callback to it, all in one go.

Additionally, this adds gears.timer.weak_start(timeout, callback). The weak
version still allows the callback function to be garbage collected and will then
stop the timer.

This was tested with the following code:

  require("gears.timer").start(0.3, function()
    print("ping")
    if collectgarbage("step", 500) then
      print("collection done")
      error("err")
    end
    return true end)
  require("gears.timer").weak_start(0.1, function()
    io.stdout:write(".")
    return true
  end)

After a full collection cycle, both timers are stopped. The first one is stopped
because of the error() that it generated. The second one is stopped because the
callback function was garbage collected.

Ref: https://github.com/awesomeWM/awesome/issues/216

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-08-11 13:21:32 +02:00
parent a166f86864
commit 0367af2be9
1 changed files with 40 additions and 0 deletions

View File

@ -103,6 +103,46 @@ timer.new = function(args)
return ret
end
--- Create a timeout for calling some callback function.
-- When the callback function returns true, it will be called again after the
-- same timeout. If false is returned, no more calls will be done. If the
-- callback function causes an error, no more calls are done.
-- @tparam number timeout Timeout in seconds (e.g. 1.5).
-- @tparam function callback Function to run.
-- @see timer.weak_start_new
function timer.start_new(timeout, callback)
local t = timer.new({ timeout = timeout })
t:connect_signal("timeout", function()
local success, cont = xpcall(callback, function(err)
print(debug.traceback("Error during executing timeout handler: "..tostring(err), 2))
end)
if not success or not cont then
t:stop()
end
end)
t:start()
return t
end
--- Create a timeout for calling some callback function.
-- This function is almost identical to `timer.start_new`. The only difference
-- is that this does not prevent the callback function from being garbage
-- collected. After the callback function was collected, the timer returned
-- will automatically be stopped.
-- @tparam number timeout Timeout in seconds (e.g. 1.5).
-- @tparam function callback Function to start.
-- @see timer.start_new
function timer.weak_start_new(timeout, callback)
local indirection = setmetatable({}, { __mode = "v" })
indirection.callback = callback
return timer.start_new(timeout, function()
local cb = indirection.callback
if cb then
return cb()
end
end)
end
local delayed_calls = {}
capi.awesome.connect_signal("refresh", function()
for _, callback in ipairs(delayed_calls) do