diff options
| author | ruki <[email protected]> | 2019-12-15 13:16:17 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-12-15 13:16:17 +0800 |
| commit | f72910c44225935a42b73b2b986c26f958efe5f7 (patch) | |
| tree | 0830d05150eabe464aedfc3ae0bf8a13414715b5 | |
| parent | f5bd3bee06639bee0556b5f3b5f1e5516db31074 (diff) | |
kill all suspended tasks
| -rw-r--r-- | xmake/core/base/scheduler.lua | 56 | ||||
| -rw-r--r-- | xmake/core/base/timer.lua | 15 |
2 files changed, 66 insertions, 5 deletions
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua index 02e52b421..486f04dc0 100644 --- a/xmake/core/base/scheduler.lua +++ b/xmake/core/base/scheduler.lua @@ -146,6 +146,11 @@ function scheduler:_sockevents_cb(sock, sockevents) timer_task.cancel = true end + -- the scheduler has been stopped? mark events as error to stop the coroutine + if not self._STARTED then + sockevents = poller.EV_SOCK_ERROR + end + -- resume this coroutine task self:_co_suspended_set(sock, nil) self:co_resume(running, (bit.band(sockevents, poller.EV_SOCK_ERROR) ~= 0) and -1 or sockevents) @@ -188,9 +193,14 @@ function scheduler:co_start_named(coname, cotask, ...) end)) self:co_tasks()[co:thread()] = co self._CO_COUNT = self:co_count() + 1 - local ok, errors = scheduler:co_resume(co, ...) - if not ok then - return nil, errors + if self._STARTED then + local ok, errors = self:co_resume(co, ...) + if not ok then + return nil, errors + end + else + self._CO_READY_TASKS = self._CO_READY_TASKS or {} + table.insert(self._CO_READY_TASKS, {co, table.pack(...)}) end return co end @@ -235,6 +245,11 @@ function scheduler:sock_wait(sock, events, timeout) return -1, "we must call waitsock() in coroutine with scheduler!" end + -- is stopped? + if not self._STARTED then + return -1, "the scheduler is stopped!" + end + -- enable edge-trigger mode if be supported if poller:support(poller.OT_SOCK, poller.EV_SOCK_CLEAR) then events = bit.bor(events, poller.EV_SOCK_CLEAR) @@ -282,6 +297,7 @@ function scheduler:sock_wait(sock, events, timeout) local timer_task = nil if timeout > 0 then timer_task = self:_timer():post(function (cancel) + print(cancel, running) if not cancel and running:is_suspended() then self:co_resume(running, 0) end @@ -331,6 +347,11 @@ function scheduler:sleep(ms) 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 @@ -357,6 +378,20 @@ function scheduler:runloop() -- start loop self._STARTED = true + -- start all ready coroutine tasks + local co_ready_tasks = self._CO_READY_TASKS + if co_ready_tasks then + for _, task in pairs(co_ready_tasks) do + local co = task[1] + local argv = task[2] + local ok, errors = self:co_resume(co, table.unpack(argv)) + if not ok then + return false, errors + end + end + end + self._CO_READY_TASKS = nil + -- run loop opt = opt or {} local ok = true @@ -399,9 +434,20 @@ function scheduler:runloop() -- mark the loop as stopped first self._STARTED = false - -- TODO resume all suspended tasks + -- 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 timeout tasks and trigger them + self:_timer():kill() -- finished return ok, errors diff --git a/xmake/core/base/timer.lua b/xmake/core/base/timer.lua index 7c81f1dd2..d2120b466 100644 --- a/xmake/core/base/timer.lua +++ b/xmake/core/base/timer.lua @@ -98,6 +98,21 @@ function timer:next() end end +-- kill all timer tasks +function timer:kill() + local tasks = self:_tasks() + while tasks:length() > 0 do + local task = tasks:peek() + if task then + tasks:pop() + if task.func then + -- cancel it + task.func(true) + end + end + end +end + -- get timer name function timer:name() return self._NAME |
