Skip to content

Instantly share code, notes, and snippets.

@prozacgod
Created May 24, 2017 03:52
Show Gist options
  • Save prozacgod/077aafa76f8ee7b786babe3ed710912d to your computer and use it in GitHub Desktop.
Save prozacgod/077aafa76f8ee7b786babe3ed710912d to your computer and use it in GitHub Desktop.
opencomputers coroutine event microkernel
--[[
Establishing ground:
write a generic coroutine kernel loop, event requests pass back to the main
control loop
also lets write 2 coroutines, and manage a list of them
RESULT:
]]
local term = require("term")
local event = require("event")
term.clear()
local function pullEvent(evt)
return coroutine.yield(evt)
end
-- this function will exit when 'q' is pressed
local function keyboardExitThreadlet()
print ("starting thread!, press q for this thread to die")
while true do
local evt, addr, a, b, c, d, e, f = pullEvent('key_up')
-- q pressed filter, lets exit!
if evt == "key_up" and a == 113 then
break
end
end
end
-- this function will print bang
local function keyboardBangThreadlet()
print ("starting thread!, press b for bang!")
local w,h = term.getViewport()
while true do
local evt, addr, a, b, c, d, e, f = pullEvent('key_up')
-- q pressed filter, lets exit!
if evt == "key_up" and a == 98 then
local col = (w - 4) * math.random()
local row = (h - 3) * math.random()
term.setCursor(col + 1, row + 2)
term.write("BANG")
end
end
end
local function eventSpyThreadlet()
local w,h = term.getViewport()
while true do
local evt = {pullEvent()}
local evtStr = ""
for i,v in ipairs(evt) do
evtStr = evtStr .. tostring(v) .. " "
end
term.setCursor(1, h)
term.write("EVT: " .. evtStr .. " ")
end
end
-- runs all threads until a thread exists
function threadletKernel(...)
local threadlets = {}
local threadletFuncs = {...}
function threadletHandlerFactory(func)
local co = coroutine.create(func)
local evt_filter_name = nil
return {
co = co,
resume = function(evt_data)
local evt_name = nil
if evt_data ~= nil then
evt_name = evt_data[1]
end
if evt_filter_name ~= nil and evt_name ~= evt_filter_name then
return
end
if evt_data == nil then
evt_data = {}
end
local noErr, evt_filter = coroutine.resume(co, table.unpack(evt_data))
evt_filter_name = evt_filter
end
}
end
for i, func in ipairs(threadletFuncs) do
threadlets[i] = threadletHandlerFactory(func)
end
local threadCount = #threadlets
local evt_data
while true do
for i = 1, #threadlets do
threadlets[i].resume(evt_data)
end
for i = #threadlets, 1, -1 do
if coroutine.status(threadlets[i].co) == 'dead' then
table.remove(threadlets, i)
end
end
if #threadlets < threadCount then
break
end
evt_data = {event.pull()}
end
end
print("press q to exit")
threadletKernel(keyboardExitThreadlet, keyboardBangThreadlet, eventSpyThreadlet)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment