Created
May 24, 2017 03:52
-
-
Save prozacgod/077aafa76f8ee7b786babe3ed710912d to your computer and use it in GitHub Desktop.
opencomputers coroutine event microkernel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
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