summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/modules/scheduler/test.lua8
-rw-r--r--xmake/core/base/scheduler.lua49
-rw-r--r--xmake/core/base/timer.lua33
-rw-r--r--xmake/core/sandbox/modules/import/core/base/scheduler.lua13
4 files changed, 76 insertions, 27 deletions
diff --git a/tests/modules/scheduler/test.lua b/tests/modules/scheduler/test.lua
index 364b87d2d..3e5cb83b1 100644
--- a/tests/modules/scheduler/test.lua
+++ b/tests/modules/scheduler/test.lua
@@ -15,16 +15,20 @@ end
function test_sleep(t)
- --[[
+ local count = 0
local task = function (a)
local dt = os.mclock()
scheduler.sleep(500)
dt = os.mclock() - dt
t:require(dt > 100 and dt < 1000)
+ count = count + 1
+ if count == 3 then
+ scheduler.stop()
+ end
end
for i = 1, 3 do
scheduler.co_start(task)
end
- scheduler.runloop()]]
+ scheduler.runloop()
end
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua
index 95e727258..52502c066 100644
--- a/xmake/core/base/scheduler.lua
+++ b/xmake/core/base/scheduler.lua
@@ -27,6 +27,7 @@ local table = require("base/table")
local option = require("base/option")
local string = require("base/string")
local poller = require("base/poller")
+local timer = require("base/timer")
local coroutine = require("base/coroutine")
-- new a coroutine instance
@@ -83,15 +84,24 @@ function _coroutine:__gc()
self._THREAD = nil
end
+-- get the timer of scheduler
+function scheduler:_timer()
+ local t = self._TIMER
+ if t == nil then
+ t = timer:new()
+ self._TIMER = t
+ end
+ return t
+end
+
-- wait the current coroutine
-function scheduler:_co_wait()
- -- TODO
- self:co_suspend()
+function scheduler:_co_wait(...)
+ return self:co_suspend(...)
end
-- wake the given coroutine
-function scheduler:_co_wake(co)
- -- TODO
+function scheduler:_co_wake(co, ...)
+ return self:co_resume(co, ...)
end
-- start a new coroutine task
@@ -146,27 +156,27 @@ end
-- sleep some times (ms)
function scheduler:sleep(ms)
-
- print(require("sys"))
- print("sleep", ms)
-
- self:_co_wait()
+ local running = self:co_running()
+ if not running then
+ return false, "we must call sleep() in coroutine with scheduler!"
+ end
+ self:_timer():post(function (cancel)
+ self:co_resume(running)
+ end, ms)
+ self:co_suspend()
return true
end
--- the loop is started?
-function scheduler:is_started()
- return self._STARTED
-end
-
-- stop the scheduler loop
function scheduler:stop()
-- TODO post a kill signal to poller
+ -- stop timer and cancel all tasks
self._STARTED = false
+ return true
end
-- run loop, schedule coroutine with socket/io and sub-processes
-function scheduler:runloop(opt)
+function scheduler:runloop()
-- start loop
self._STARTED = true
@@ -175,9 +185,12 @@ function scheduler:runloop(opt)
opt = opt or {}
local ok = true
local errors = nil
- local timeout = opt.timeout or -1
+ local timeout = -1
while self._STARTED do
+ -- get the next timeout
+ timeout = self:_timer():delay() or 1000
+
-- wait events
local count, events = poller:wait(timeout)
if count < 0 then
@@ -187,7 +200,7 @@ function scheduler:runloop(opt)
end
-- spank the timer and trigger all timeout tasks
- -- TODO
+ self:_timer():next()
-- resume all suspended tasks with events
-- TODO
diff --git a/xmake/core/base/timer.lua b/xmake/core/base/timer.lua
index 28490f01c..7c81f1dd2 100644
--- a/xmake/core/base/timer.lua
+++ b/xmake/core/base/timer.lua
@@ -37,7 +37,7 @@ end
-- post timer task after delay and will be auto-remove it after be expired
function timer:post(func, delay, opt)
- return self:post_at(task, os.mclock() + delay, delay, opt)
+ return self:post_at(func, os.mclock() + delay, delay, opt)
end
-- post timer task at the absolute time and will be auto-remove it after be expired
@@ -58,7 +58,7 @@ end
-- get the delay of next task
function timer:delay()
- local delay = -1
+ local delay = nil
local tasks = self:_tasks()
if tasks:length() > 0 then
local task = tasks:peek()
@@ -70,9 +70,32 @@ function timer:delay()
return delay
end
--- run the timer loop
-function timer:runloop()
- -- TODO
+-- run the timer next loop
+function timer:next()
+ local tasks = self:_tasks()
+ while tasks:length() > 0 do
+ local triggered = false
+ local task = tasks:peek()
+ if task then
+ -- timeout?
+ local now = os.mclock()
+ if task.when <= now then
+ tasks:pop()
+ if task.continuous and not task.cancel then
+ task.when = now + task.period
+ tasks:push(task)
+ end
+ -- run timer task
+ if task.func then
+ task.func(task.cancel)
+ triggered = true
+ end
+ end
+ end
+ if not triggered then
+ break
+ end
+ end
end
-- get timer name
diff --git a/xmake/core/sandbox/modules/import/core/base/scheduler.lua b/xmake/core/sandbox/modules/import/core/base/scheduler.lua
index ff6576793..0a1189459 100644
--- a/xmake/core/sandbox/modules/import/core/base/scheduler.lua
+++ b/xmake/core/sandbox/modules/import/core/base/scheduler.lua
@@ -66,9 +66,18 @@ function sandbox_core_base_scheduler.sleep(ms)
end
end
+
+-- stop loop
+function sandbox_core_base_scheduler.stop()
+ local ok, errors = scheduler:stop()
+ if not ok then
+ raise(errors)
+ end
+end
+
-- run loop
-function sandbox_core_base_scheduler.runloop(opt)
- local ok, errors = scheduler:runloop(opt)
+function sandbox_core_base_scheduler.runloop()
+ local ok, errors = scheduler:runloop()
if not ok then
raise(errors)
end