mirror of
https://github.com/britzl/monarch.git
synced 2025-09-28 02:22:20 +02:00
Make sure that callbacks aren't invoked more than once
This commit is contained in:
47
monarch/utils/async.lua
Normal file
47
monarch/utils/async.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
local M = {}
|
||||
|
||||
local NOT_STARTED = "not_started"
|
||||
local YIELDED = "yielded"
|
||||
local RESUMED = "resumed"
|
||||
local RUNNING = "running"
|
||||
|
||||
function M.async(fn)
|
||||
local co = coroutine.running()
|
||||
|
||||
local state = NOT_STARTED
|
||||
|
||||
local function await(fn, ...)
|
||||
state = RUNNING
|
||||
fn(...)
|
||||
if state ~= RUNNING then
|
||||
return
|
||||
end
|
||||
state = YIELDED
|
||||
local r = { coroutine.yield() }
|
||||
return unpack(r)
|
||||
end
|
||||
|
||||
local function resume(...)
|
||||
if state ~= RUNNING then
|
||||
state = RUNNING
|
||||
local ok, err = coroutine.resume(co, ...)
|
||||
if not ok then
|
||||
print(err)
|
||||
print(debug.traceback())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if co then
|
||||
return fn(await, resume)
|
||||
else
|
||||
co = coroutine.create(fn)
|
||||
return resume(await, resume)
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable(M, {
|
||||
__call = function(t, ...)
|
||||
return M.async(...)
|
||||
end
|
||||
})
|
@@ -6,13 +6,18 @@ function M.create()
|
||||
|
||||
local callback = nil
|
||||
local callback_count = 0
|
||||
local all_callbacks_done = false
|
||||
|
||||
local function is_done()
|
||||
return callback_count == 0
|
||||
end
|
||||
|
||||
local function invoke_if_done()
|
||||
if all_callbacks_done then
|
||||
print("Warning: The same callback will be invoked twice from the callback tracker!", id or "")
|
||||
end
|
||||
if callback_count == 0 and callback then
|
||||
all_callbacks_done = true
|
||||
local ok, err = pcall(callback)
|
||||
if not ok then print(err) end
|
||||
end
|
||||
@@ -41,20 +46,6 @@ function M.create()
|
||||
invoke_if_done()
|
||||
end
|
||||
|
||||
function instance.yield_until_done()
|
||||
local co = coroutine.running()
|
||||
callback = function()
|
||||
local ok, err = coroutine.resume(co)
|
||||
if not ok then
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
invoke_if_done()
|
||||
if not is_done() then
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
|
||||
return instance
|
||||
end
|
||||
|
||||
|
Reference in New Issue
Block a user