summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2020-02-04 00:35:32 +0800
committerruki <[email protected]>2020-02-07 22:45:56 +0800
commit486cc3bb146e19542991fd2ac3ac385f101bde1a (patch)
tree1c455d39efd6489ceccdb6c1c9b902a7a60da8a4
parent81f94cfcc81beb8a0218506108813ceeb7eb9048 (diff)
add scheduler.co_yield
-rw-r--r--tests/modules/scheduler/sleep.lua26
-rw-r--r--tests/modules/scheduler/yield.lua15
-rw-r--r--xmake/core/base/scheduler.lua103
-rw-r--r--xmake/core/sandbox/modules/import/core/base/scheduler.lua13
-rw-r--r--xmake/core/sandbox/modules/os.lua2
5 files changed, 124 insertions, 35 deletions
diff --git a/tests/modules/scheduler/sleep.lua b/tests/modules/scheduler/sleep.lua
new file mode 100644
index 000000000..5c6976a07
--- /dev/null
+++ b/tests/modules/scheduler/sleep.lua
@@ -0,0 +1,26 @@
+import("core.base.scheduler")
+
+function _session2(id)
+ print("session2: %d ..", id)
+ local dt = os.mclock()
+ os.sleep(1000)
+ dt = os.mclock() - dt
+ print("session2: %d end, dt: %d ms", id, dt)
+end
+
+function _session1(id)
+ print("session1: %d ..", id)
+ local dt = os.mclock()
+ scheduler.co_sleep(1000)
+ dt = os.mclock() - dt
+ print("session1: %d end, dt: %d ms", id, dt)
+end
+
+function main()
+ for i = 1, 10 do
+ scheduler.co_start(_session1, i)
+ scheduler.co_start(_session2, i)
+ end
+ scheduler.runloop()
+end
+
diff --git a/tests/modules/scheduler/yield.lua b/tests/modules/scheduler/yield.lua
new file mode 100644
index 000000000..f884a0199
--- /dev/null
+++ b/tests/modules/scheduler/yield.lua
@@ -0,0 +1,15 @@
+import("core.base.scheduler")
+
+function _session(id)
+ print("test: %d ..", id)
+ scheduler.co_yield()
+ print("test: %d end", id)
+end
+
+function main()
+ for i = 1, 10 do
+ scheduler.co_start(_session, i)
+ end
+ scheduler.runloop()
+end
+
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua
index 1464ae2dc..1c6db570d 100644
--- a/xmake/core/base/scheduler.lua
+++ b/xmake/core/base/scheduler.lua
@@ -251,6 +251,13 @@ end
-- start a new named coroutine task
function scheduler:co_start_named(coname, cotask, ...)
+
+ -- check coroutine task
+ if not cotask then
+ return nil, string.format("cannot start coroutine, invalid cotask(%s/%s)", coname and coname or "anonymous", cotask)
+ end
+
+ -- start coroutine
local co
co = _coroutine.new(coname, coroutine.create(function(...)
cotask(...)
@@ -283,6 +290,71 @@ function scheduler:co_suspend(...)
return coroutine.yield(...)
end
+-- yield the current coroutine
+function scheduler:co_yield()
+
+ -- get the running coroutine
+ local running = self:co_running()
+ if not running then
+ return false, "we must call co_yield() in coroutine with scheduler!"
+ end
+
+ -- is stopped?
+ if not self._STARTED then
+ return false, "the scheduler is stopped!"
+ end
+
+ -- register timeout task to timer without 0 ms (no delay)
+ self:_timer():post(function (cancel)
+ if running:is_suspended() then
+ self:_co_tasks_suspended():remove(running)
+ self:co_resume(running)
+ end
+ end, 0)
+
+ -- save the suspended coroutine
+ self:_co_tasks_suspended():insert(running)
+
+ -- wait
+ self:co_suspend()
+ return true
+end
+
+-- sleep some times (ms)
+function scheduler:co_sleep(ms)
+
+ -- we need not do sleep
+ if ms == 0 then
+ return true
+ end
+
+ -- get the running coroutine
+ local running = self:co_running()
+ if not running then
+ return false, "we must call sleep() in coroutine with scheduler!"
+ end
+
+ -- is stopped?
+ if not self._STARTED then
+ return false, "the scheduler is stopped!"
+ end
+
+ -- register timeout task to timer
+ self:_timer():post(function (cancel)
+ if running:is_suspended() then
+ self:_co_tasks_suspended():remove(running)
+ self:co_resume(running)
+ end
+ end, ms)
+
+ -- save the suspended coroutine
+ self:_co_tasks_suspended():insert(running)
+
+ -- wait
+ self:co_suspend()
+ return true
+end
+
-- get the current running coroutine
function scheduler:co_running()
local running = coroutine.running()
@@ -499,37 +571,6 @@ function scheduler:poller_cancel(obj)
return true
end
--- sleep some times (ms)
-function scheduler:sleep(ms)
-
- -- we need not do sleep
- if ms == 0 then
- return true
- end
-
- -- get the running coroutine
- local running = self:co_running()
- if not running then
- return false, "we must call sleep() in coroutine with scheduler!"
- end
-
- -- is stopped?
- if not self._STARTED then
- return false, "the scheduler is stopped!"
- end
-
- -- register timeout task to timer
- self:_timer():post(function (cancel)
- if running:is_suspended() then
- self:co_resume(running)
- end
- end, ms)
-
- -- wait
- self:co_suspend()
- return true
-end
-
-- stop the scheduler loop
function scheduler:stop()
-- mark scheduler status as stopped and spank the poller:wait()
diff --git a/xmake/core/sandbox/modules/import/core/base/scheduler.lua b/xmake/core/sandbox/modules/import/core/base/scheduler.lua
index cdd1ad586..3476c9333 100644
--- a/xmake/core/sandbox/modules/import/core/base/scheduler.lua
+++ b/xmake/core/sandbox/modules/import/core/base/scheduler.lua
@@ -53,6 +53,14 @@ function sandbox_core_base_scheduler.co_suspend(...)
return scheduler:co_suspend(...)
end
+-- yield the current coroutine
+function sandbox_core_base_scheduler.co_yield()
+ local ok, errors = scheduler:co_yield()
+ if not ok then
+ raise(errors)
+ end
+end
+
-- get the current running coroutine
function sandbox_core_base_scheduler.co_running()
return scheduler:co_running()
@@ -64,14 +72,13 @@ function sandbox_core_base_scheduler.co_count()
end
-- sleep some times (ms)
-function sandbox_core_base_scheduler.sleep(ms)
- local ok, errors = scheduler:sleep(ms)
+function sandbox_core_base_scheduler.co_sleep(ms)
+ local ok, errors = scheduler:co_sleep(ms)
if not ok then
raise(errors)
end
end
-
-- stop loop
function sandbox_core_base_scheduler.stop()
local ok, errors = scheduler:stop()
diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua
index 10323b438..b69c68f25 100644
--- a/xmake/core/sandbox/modules/os.lua
+++ b/xmake/core/sandbox/modules/os.lua
@@ -484,7 +484,7 @@ end
-- sleep (support in coroutine)
function sandbox_os.sleep(ms)
if scheduler:co_running() then
- local ok, errors = scheduler:sleep(ms)
+ local ok, errors = scheduler:co_sleep(ms)
if not ok then
raise(errors)
end