Skip to content
Permalink
Browse files
Added hook system. Began work on experimental overarching thread syst…
…em. Added unpack method to see.base.Array for converting to varargs.
  • Loading branch information
James King committed Aug 10, 2013
1 parent de68e1f commit 4c35829
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 14 deletions.
@@ -167,11 +167,84 @@ function StandardGlobals.STR(vm, str)
return vm.base.String.new(str)
end

ThreadPool = { }
ThreadPool.__index = ThreadPool

--[[
Creates a new ThreadPool.
]]
function ThreadPool.new()
local self = { }
setmetatable(self, ThreadPool)
self.threads = { }
self.current = { }
self.eventFilters = { }
self.eventData = { }
return self
end

--[[
Runs a thread in this ThreadPool.
]]
function ThreadPool:runThread(i)
self.current = self.threads[i]
local co = self.threads[i].co

if not self.eventFilters[co] or self.eventFilters[co] == self.eventData[1] or self.eventData[1] == "terminate" then
local ok, param = coroutine.resume(co, unpack(self.eventData))

if ok then
self.eventFilters[co] = param
else
table.remove(self.threads, i)
end

if coroutine.status(co) == "dead" then
self.threads[i].id = -1
self.threads[i].co = nil
table.remove(self.threads, i)
end
end
end

--[[
Runs the threads, passing event data to each one.
]]
function ThreadPool:waitForAll()
while #self.threads > 0 do
self:runOnce()
end
end

--[[
Runs the threads once and returns.
]]
function ThreadPool:runOnce()
for i = 1, #self.threads do
self:runThread(i)
end

self.eventData = {os.pullEventRaw()}
end

--[[
Adds a thread to this ThreadPool.
]]
function ThreadPool:add(thread)
thread.co = coroutine.create(function()
xpcall(thread.func, errorHandler)
end)
table.insert(self.threads, thread)
local id = #self.threads
self:runThread(id)
return id
end

SeeVM = { }
SeeVM.__index = SeeVM

--[[
Creates a new SeeVM
Creates a new SeeVM.
]]
function SeeVM.new(natives, seePath)
local self = { }
@@ -188,6 +261,7 @@ function SeeVM.new(natives, seePath)
self.classes = { }
self.natives = natives
self.natives.error = error
self.natives.threadpool = ThreadPool.new()
self.classPaths = { }
self.base.Object = self:loadClassFromAny("see.base.Object")
self.rt = self:loadClassFromAny("see.rt.Class")
@@ -389,7 +463,7 @@ function SeeVM:loadClass(def, annotations, name)
-- Setup class environment.
env[className] = class
setfenv(def, env)
def()
xpcall(def, errorHandler)
self.classes[name] = class

for _, annotation in pairs(annotations) do
@@ -2,7 +2,7 @@
--@native table.insert
--@native rawget
--@native rawset
--@native tostring
--@native unpack

--@import see.util.ArgumentUtils
--@import see.rt.IndexOutOfBoundsException
@@ -120,6 +120,10 @@ function Array:insert(index, value)
throw(IndexOutOfBoundsException.new(index))
end

function Array:unpack()
return unpack(self.luaArray)
end

--[[
Iterate over all the elements in this Array.
@return function An iterator.
@@ -1,5 +1,6 @@
--@native print
--@native read
--@native write
--@native unpack

--[[
@@ -26,6 +27,18 @@ function System.print(...)
print(unpack(args))
end

--[[
Writes a string to the shell.
@param see.base.String The string to write.
]]
function System.write(...)
local args = {...}
for i = 1, #args do
args[i] = cast(args[i], "string")
end
write(unpack(args))
end

-- TODO: Prevent from trashing global namespace.
function System.loadNativeAPI(path)
os.loadAPI()
@@ -1,4 +1,5 @@
--@native coroutine
--@native threadpool

Thread.SUSPENDED = "suspended"
Thread.RUNNING = "running"
@@ -13,21 +14,17 @@ function Thread.yield(...)
return coroutine.yield(...)
end

function Thread.current()
return threadpool.current
end

--[[
Constructs a new Thread.
@param function:func The function to run in a new thread.
]]
function Thread:init(func)
self.co = coroutine.create(func)
end

--[[
Resumes this Thread. Passes the given arguments to the thread as it is resumed.
@param any... Arguments to pass to the thread.
@return any... Values passed from the thread.
]]
function Thread:resume(...)
return coroutine.resume(self.co, ...)
self.func = func
self.id = threadpool:add(self)
end

--[[
@@ -0,0 +1,5 @@
function Hook:init(id, event, callback)
self.id = id
self.event = event
self.callback = callback
end
@@ -0,0 +1,38 @@
--@native os.pullEvent
--@native unpack

--@import see.hook.Hook
--@import see.concurrent.Thread

local hooks = { }
local running

function Hooks.run()
local eventData = Array.new(os.pullEvent())
if eventData:length() == 0 then
return
end
local event = eventData[1]
eventData:remove(1)
if hooks[event] then
for hook in hooks[event]:iAll() do
hook.callback(eventData:unpack())
end
end
end

function Hooks.add(event, callback)
local t = hooks[event]
if not t then
t = Array.new()
hooks[event] = t
end
local hook = Hook.new(#t + 1, event, callback)
t:add(hook)
return hook
end

function Hooks.remove(hook)
hooks[hook.event]:remove(hook.id)
hook.id = -1
end
@@ -7,6 +7,7 @@ local MAKE_PATHS = {
"lib/see/",
"lib/see/base/",
"lib/see/concurrent/",
"lib/see/hook/",
"lib/see/rt/",
"lib/see/util/",
"programs/"
@@ -20,6 +21,8 @@ local DL_PATHS = {
"lib/see/base/String.lua",
"lib/see/base/System.lua",
"lib/see/concurrent/Thread.lua",
"lib/see/hook/Hook.lua",
"lib/see/hook/Hooks.lua",
"lib/see/rt/Class.lua",
"lib/see/rt/IndexOutOfBoundsException.lua",
"lib/see/rt/InvalidArgumentException.lua",
@@ -17,6 +17,12 @@ local _, err = pcall(function(...)
local MainClass = vm:loadClassFromAny(mainClassName)
if not MainClass then error("Main class not found! ") end
if not MainClass.main then error("Main method not found!") end
--[[xpcall(function()
vm.natives.threadpool:add(vm:loadClassFromAny("see.concurrent.Thread").new(function()
MainClass.main(args)
end))
vm.natives.threadpool:waitForAll()
end, see.errorHandler)]]
xpcall(function() MainClass.main(args) end, see.errorHandler)
end

@@ -0,0 +1,21 @@
--@import see.hook.Hooks

function Test.main()
local hook
local input = true
local str = String.new()
hook = Hooks.add("char", function(c)
if c == "z" then
input = false
Hooks.remove(hook)
else
str:add(c)
end
end)

while input do
Hooks.run()
end

System.print(str)
end
2 test
@@ -1 +1 @@
shell.run("/see/programs/see", "-r", "/see/", "/see/test/", "see.example.Test", "Yevano")
shell.run("/see/programs/see", "-r", "/see/", "/see/test/", "see.dev.Test", "")

0 comments on commit 4c35829

Please sign in to comment.