summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2019-12-16 22:34:06 +0800
committerruki <[email protected]>2019-12-16 09:24:36 +0800
commit4ed6741dd366d1e48d30356657bc77d40e0ac2ca (patch)
treee070e5be51847df31c5473cb9f3957fc5ea192d8
parent77c589d08366ec183f03e54106f0899ec127feb9 (diff)
impl scheduler.stop
-rw-r--r--core/src/xmake/io/poller_spank.c48
-rw-r--r--core/src/xmake/machine.c2
-rw-r--r--core/src/xmake/makefile1
-rw-r--r--xmake/core/base/poller.lua5
-rw-r--r--xmake/core/base/scheduler.lua57
5 files changed, 87 insertions, 26 deletions
diff --git a/core/src/xmake/io/poller_spank.c b/core/src/xmake/io/poller_spank.c
new file mode 100644
index 000000000..e5f6ba5ab
--- /dev/null
+++ b/core/src/xmake/io/poller_spank.c
@@ -0,0 +1,48 @@
+/*!A cross-platform build utility based on Lua
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2015 - 2019, TBOOX Open Source Group.
+ *
+ * @author ruki
+ * @file poller_spank.c
+ *
+ */
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * trace
+ */
+#define TB_TRACE_MODULE_NAME "poller_spank"
+#define TB_TRACE_MODULE_DEBUG (0)
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * includes
+ */
+#include "prefix.h"
+#include "poller.h"
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * interfaces
+ */
+
+// io.poller_spank()
+tb_int_t xm_io_poller_spank(lua_State* lua)
+{
+ // check
+ tb_assert_and_check_return_val(lua, 0);
+
+ // spank the poller, break the tb_poller_wait() and return all events
+ tb_poller_spak(xm_io_poller());
+ return 0;
+}
+
diff --git a/core/src/xmake/machine.c b/core/src/xmake/machine.c
index 4fdc73204..28903ec3a 100644
--- a/core/src/xmake/machine.c
+++ b/core/src/xmake/machine.c
@@ -128,6 +128,7 @@ tb_int_t xm_io_socket_close(lua_State* lua);
tb_int_t xm_io_poller_insert(lua_State* lua);
tb_int_t xm_io_poller_modify(lua_State* lua);
tb_int_t xm_io_poller_remove(lua_State* lua);
+tb_int_t xm_io_poller_spank(lua_State* lua);
tb_int_t xm_io_poller_support(lua_State* lua);
tb_int_t xm_io_poller_wait(lua_State* lua);
@@ -279,6 +280,7 @@ static luaL_Reg const g_io_functions[] =
, { "poller_insert", xm_io_poller_insert }
, { "poller_modify", xm_io_poller_modify }
, { "poller_remove", xm_io_poller_remove }
+, { "poller_spank", xm_io_poller_spank }
, { "poller_support", xm_io_poller_support }
, { "poller_wait", xm_io_poller_wait }
, { tb_null, tb_null }
diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile
index 67a340933..935e210a6 100644
--- a/core/src/xmake/makefile
+++ b/core/src/xmake/makefile
@@ -65,6 +65,7 @@ xmake_C_FILES += \
io/poller_insert \
io/poller_remove \
io/poller_modify \
+ io/poller_spank \
io/poller_support \
io/socket_open \
io/socket_rawfd \
diff --git a/xmake/core/base/poller.lua b/xmake/core/base/poller.lua
index f964ae8bc..8c4085670 100644
--- a/xmake/core/base/poller.lua
+++ b/xmake/core/base/poller.lua
@@ -120,6 +120,11 @@ function poller:support(otype, events)
return false, string.format("invalid poller object type(%d)!", otype)
end
+-- spank poller to break the wait() and return all triggered events
+function poller:spank()
+ io.poller_spank()
+end
+
-- insert object events to poller
function poller:insert(otype, obj, events, udata)
if otype == poller.OT_SOCK then
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua
index b8f3ca8c1..50e42c5b6 100644
--- a/xmake/core/base/scheduler.lua
+++ b/xmake/core/base/scheduler.lua
@@ -129,7 +129,7 @@ function scheduler:_sockevents_cb(sock, sockevents)
local events_prev_save = bit.rshift(events_prev, 16)
-- is waiting?
- local running = self:_co_suspended(sock)
+ local running = self:_co_sock_suspended(sock)
if running and running:is_suspended() then
-- eof for edge trigger?
@@ -152,7 +152,7 @@ function scheduler:_sockevents_cb(sock, sockevents)
end
-- resume this coroutine task
- self:_co_suspended_set(sock, nil)
+ self:_co_sock_suspended_set(sock, nil)
self:co_resume(running, (bit.band(sockevents, poller.EV_SOCK_ERROR) ~= 0) and -1 or sockevents)
else
-- cache socket events
@@ -162,18 +162,32 @@ function scheduler:_sockevents_cb(sock, sockevents)
end
-- get the suspended coroutine task
-function scheduler:_co_suspended(key)
- return self._CO_SUSPENDED_TASKS and self._CO_SUSPENDED_TASKS[key] or nil
+function scheduler:_co_sock_suspended(sock)
+ return self._CO_SOCK_SUSPENDED_TASKS and self._CO_SOCK_SUSPENDED_TASKS[sock] or nil
end
-- set the suspended coroutine task
-function scheduler:_co_suspended_set(key, co)
- local co_suspended_tasks = self._CO_SUSPENDED_TASKS
- if not co_suspended_tasks then
- co_suspended_tasks = {}
- self._CO_SUSPENDED_TASKS = co_suspended_tasks
+function scheduler:_co_sock_suspended_set(sock, co)
+ local co_sock_suspended_tasks = self._CO_SOCK_SUSPENDED_TASKS
+ if not co_sock_suspended_tasks then
+ co_sock_suspended_tasks = {}
+ self._CO_SOCK_SUSPENDED_TASKS = co_sock_suspended_tasks
+ end
+ co_sock_suspended_tasks[sock] = co
+end
+
+-- cancel and resume all suspended socket tasks after stopping scheduler
+-- we cannot suspend them forever, all tasks will be exited directly and free all resources.
+function scheduler:_co_sock_suspended_cancel_all()
+ local co_sock_suspended_tasks = self._CO_SOCK_SUSPENDED_TASKS
+ if co_sock_suspended_tasks then
+ for _, co in pairs(co_sock_suspended_tasks) do
+ local ok, errors = self:co_resume(co, -1)
+ if not ok then
+ return false, errors
+ end
+ end
end
- co_suspended_tasks[key] = co
end
-- start a new coroutine task
@@ -298,7 +312,7 @@ function scheduler:sock_wait(sock, events, timeout)
if timeout > 0 then
timer_task = self:_timer():post(function (cancel)
if not cancel and running:is_suspended() then
- self:_co_suspended_set(sock, nil)
+ self:_co_sock_suspended_set(sock, nil)
self:co_resume(running, 0)
end
end, timeout)
@@ -309,7 +323,7 @@ function scheduler:sock_wait(sock, events, timeout)
self:_sockevents_set(sock:csock(), events)
-- save the suspended coroutine
- self:_co_suspended_set(sock, running)
+ self:_co_sock_suspended_set(sock, running)
-- wait
return self:co_suspend()
@@ -328,7 +342,7 @@ function scheduler:sock_cancel(sock)
return false, errors
end
self:_sockevents_set(sock:csock(), 0)
- self:_co_suspended_set(sock, nil)
+ self:_co_sock_suspended_set(sock, nil)
end
return true
end
@@ -366,9 +380,9 @@ end
-- stop the scheduler loop
function scheduler:stop()
- -- TODO post a kill signal to poller
- -- stop timer and cancel all tasks
+ -- mark scheduler status as stopped and spank the poller:wait()
self._STARTED = false
+ poller:spank()
return true
end
@@ -434,17 +448,8 @@ function scheduler:runloop()
-- mark the loop as stopped first
self._STARTED = false
- -- resume all suspended tasks after stopping scheduler
- -- we cannot suspend them now, all tasks will be exited directly and free all resources.
- local co_suspended_tasks = self._CO_SUSPENDED_TASKS
- if co_suspended_tasks then
- for _, co in pairs(co_suspended_tasks) do
- local ok, errors = self:co_resume(co)
- if not ok then
- return false, errors
- end
- end
- end
+ -- cancel all suspended tasks after stopping scheduler
+ self:_co_sock_suspended_cancel_all()
-- cancel all timeout tasks and trigger them
self:_timer():kill()