summaryrefslogtreecommitdiff
path: root/script-beta/await.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script-beta/await.lua')
-rw-r--r--script-beta/await.lua100
1 files changed, 100 insertions, 0 deletions
diff --git a/script-beta/await.lua b/script-beta/await.lua
new file mode 100644
index 00000000..5a960e96
--- /dev/null
+++ b/script-beta/await.lua
@@ -0,0 +1,100 @@
+local timer = require 'timer'
+
+---@class await
+local m = {}
+m.type = 'await'
+
+m.coTracker = setmetatable({}, { __mode = 'k' })
+m.delayQueue = {}
+m.delayQueueIndex = 1
+
+--- 设置错误处理器
+---@param errHandle function {comment = '当有错误发生时,会以错误堆栈为参数调用该函数'}
+function m.setErrorHandle(errHandle)
+ m.errorHandle = errHandle
+end
+
+function m.checkResult(co, ...)
+ local suc, err = ...
+ if not suc and m.errorHandle then
+ m.errorHandle(debug.traceback(co, err))
+ end
+ return ...
+end
+
+--- 创建一个任务
+function m.create(callback, ...)
+ local co = coroutine.create(callback)
+ m.coTracker[co] = true
+ return m.checkResult(co, coroutine.resume(co, ...))
+end
+
+--- 休眠一段时间
+---@param time number
+function m.sleep(time, getVersion)
+ if not coroutine.isyieldable() then
+ if m.errorHandle then
+ m.errorHandle(debug.traceback('Cannot yield'))
+ end
+ return
+ end
+ local version = getVersion and getVersion()
+ local co = coroutine.running()
+ timer.wait(time, function ()
+ if version == (getVersion and getVersion()) then
+ return m.checkResult(co, coroutine.resume(co))
+ else
+ coroutine.close(co)
+ end
+ end)
+ return coroutine.yield(getVersion)
+end
+
+--- 等待直到唤醒
+---@param callback function
+function m.wait(callback, ...)
+ if not coroutine.isyieldable() then
+ return
+ end
+ local co = coroutine.running()
+ callback(function (...)
+ return m.checkResult(co, coroutine.resume(co, ...))
+ end)
+ return coroutine.yield(...)
+end
+
+--- 延迟
+function m.delay(getVersion)
+ if not coroutine.isyieldable() then
+ return
+ end
+ local co = coroutine.running()
+ local version = getVersion and getVersion()
+ m.delayQueue[#m.delayQueue+1] = function ()
+ if version == (getVersion and getVersion()) then
+ return m.checkResult(co, coroutine.resume(co))
+ else
+ coroutine.close(co)
+ end
+ end
+ return coroutine.yield()
+end
+
+--- 步进
+function m.step()
+ local waker = m.delayQueue[m.delayQueueIndex]
+ if waker then
+ m.delayQueue[m.delayQueueIndex] = false
+ m.delayQueueIndex = m.delayQueueIndex + 1
+ waker()
+ return true
+ else
+ for i = 1, #m.delayQueue do
+ m.delayQueue[i] = nil
+ end
+ m.delayQueueIndex = 1
+ return false
+ end
+end
+
+return m