-
Notifications
You must be signed in to change notification settings - Fork 8
/
dispatcher.lua
66 lines (57 loc) · 1.91 KB
/
dispatcher.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
--[[
Coroutine dispatcher design questions, approach and constraints:
- Dispatcher will have startup, mainloop and cleanup sections.
Tasks can supply corresponding functions that runs for each of
these sections.
- Tasks that propogates an error are considered dead and will
be removed on next iteration.
- Each task should be a wrapped closure or coroutine?
Leaning towards closure. A timeup parameter will be bound to the closure.
- Each task needs a timeup parameter affecting how often it's executed.
- Need a way to add/remove tasks from the dispatcher list.
--]]
local ffi = require 'ffi'
ffi.cdef [[void Sleep (int ms);]]
local Sleep = ffi.C.Sleep
local timeout_period = 100
local dispatcher = { startup_tasks = {}, shutdown_tasks = {}, tasks = {} }
function dispatcher.addtask (f, timesup)
timesup = timesup or timeout_period / 1000
local log = require 'tools.logger' "Dispatcher"
local co = coroutine.create (f)
local clock = os.clock
local resume, status = coroutine.resume, coroutine.status
local next_run = timesup + clock ()
local task = function ()
if clock () > next_run then
local noerr, errmsg = resume (co)
log._if (not noerr, errmsg)
next_run = timesup + clock ()
end
return status (co)
end
table.insert (dispatcher.tasks, task)
end
function dispatcher.startup ()
for _, each in ipairs (dispatcher.startup_tasks) do
each ()
end
end
function dispatcher.mainloop ()
local tasks = dispatcher.tasks
local front = #tasks
while #tasks > 0 do
local status = tasks[front] ()
if status == "dead" then
table.remove (tasks, front)
end
front = front == 1 and #tasks or (front - 1)
Sleep (timeout_period)
end
end
function dispatcher.shutdown ()
for _, each in ipairs (dispatcher.shutdown_tasks) do
each ()
end
end
return dispatcher