luaforwindows/files/lua/loop/thread/IOScheduler.lua

171 lines
7.2 KiB
Lua
Executable File

--------------------------------------------------------------------------------
---------------------- ## ##### ##### ###### -----------------------
---------------------- ## ## ## ## ## ## ## -----------------------
---------------------- ## ## ## ## ## ###### -----------------------
---------------------- ## ## ## ## ## ## -----------------------
---------------------- ###### ##### ##### ## -----------------------
---------------------- -----------------------
----------------------- Lua Object-Oriented Programming ------------------------
--------------------------------------------------------------------------------
-- Project: LOOP Class Library --
-- Release: 2.3 beta --
-- Title : Cooperative Threads Scheduler with Integrated I/O --
-- Author : Renato Maia <maia@inf.puc-rio.br> --
--------------------------------------------------------------------------------
--[[VERBOSE]] local rawget = rawget
--[[VERBOSE]] local tostring = tostring
local ipairs = ipairs
local getmetatable = getmetatable
local math = require "math"
local oo = require "loop.simple"
local MapWithArrayOfKeys = require "loop.collection.MapWithArrayOfKeys"
local Scheduler = require "loop.thread.Scheduler"
module "loop.thread.IOScheduler"
oo.class(_M, Scheduler)
--------------------------------------------------------------------------------
-- Initialization Code ---------------------------------------------------------
--------------------------------------------------------------------------------
function __init(class, self)
self = Scheduler.__init(class, self)
self.reading = MapWithArrayOfKeys()
self.writing = MapWithArrayOfKeys()
return self
end
__init(getmetatable(_M), _M)
--------------------------------------------------------------------------------
-- Internal Functions ----------------------------------------------------------
--------------------------------------------------------------------------------
function signalall(self, timeout) --[[VERBOSE]] local verbose = self.verbose
if timeout then timeout = math.max(timeout - self:time(), 0) end
local reading, writing = self.reading, self.writing
if #reading > 0 or #writing > 0 then --[[VERBOSE]] verbose:scheduler(true, "signaling blocked threads for ",timeout," seconds")
local running = self.running
local readok, writeok = self.select(reading, writing, timeout)
local index = 1
while index <= #reading do
local channel = reading[index]
if readok[channel] then --[[VERBOSE]] verbose:threads("unblocking reading ",reading[channel])
running:enqueue(reading[channel])
reading:removeat(index)
else
index = index + 1
end
end
index = 1
while index <= #writing do
local channel = writing[index]
if writeok[channel] then --[[VERBOSE]] verbose:threads("unblocking writing ", writing[channel])
running:enqueue(writing[channel])
writing:removeat(index)
else
index = index + 1
end
end --[[VERBOSE]] verbose:scheduler(false, "blocked threads signaled")
return true
elseif timeout and timeout > 0 then --[[VERBOSE]] verbose:scheduler("no threads blocked, sleeping for ",timeout," seconds")
self.sleep(timeout)
end
return false
end
--------------------------------------------------------------------------------
-- Customizable Behavior -------------------------------------------------------
--------------------------------------------------------------------------------
idle = signalall
--------------------------------------------------------------------------------
-- Exported API ----------------------------------------------------------------
--------------------------------------------------------------------------------
function register(self, routine, previous)
local reading, writing = self.reading, self.writing
for _, channel in ipairs(reading) do
if reading[channel] == routine then return end
end
for _, channel in ipairs(writing) do
if writing[channel] == routine then return end
end
return Scheduler.register(self, routine, previous)
end
local function handleremoved(self, routine, removed, ...)
local reading, writing = self.reading, self.writing
local index = 1
while index <= #reading do
local channel = reading[index]
if reading[channel] == routine then
reading:removeat(index)
removed = routine
else
index = index + 1
end
end
index = 1
while index <= #writing do
local channel = writing[index]
if writing[channel] == routine then
writing:removeat(index)
removed = routine
else
index = index + 1
end
end
return removed, ...
end
function remove(self, routine)
return handleremoved(self, routine, Scheduler.remove(self, routine))
end
--------------------------------------------------------------------------------
-- Control Functions -----------------------------------------------------------
--------------------------------------------------------------------------------
function step(self, ...) --[[VERBOSE]] local verbose = self.verbose; verbose:scheduler(true, "performing scheduling step")
local signaled = self:signalall(0)
local wokenup = self:wakeupall()
local resumed = self:resumeall(nil, ...) --[[VERBOSE]] verbose:scheduler(false, "scheduling step performed")
return signaled or wokenup or resumed
end
--------------------------------------------------------------------------------
-- Verbose Support -------------------------------------------------------------
--------------------------------------------------------------------------------
--[[VERBOSE]] local oldfunc = verbose.custom.threads
--[[VERBOSE]] function verbose.custom:threads(...)
--[[VERBOSE]] local viewer = self.viewer
--[[VERBOSE]] local output = self.viewer.output
--[[VERBOSE]]
--[[VERBOSE]] oldfunc(self, ...)
--[[VERBOSE]]
--[[VERBOSE]] local scheduler = rawget(self, "schedulerdetails")
--[[VERBOSE]] if scheduler then
--[[VERBOSE]] local newline = "\n"..viewer.prefix..viewer.indentation
--[[VERBOSE]]
--[[VERBOSE]] output:write(newline)
--[[VERBOSE]] output:write("Reading:")
--[[VERBOSE]] for _, current in ipairs(scheduler.reading) do
--[[VERBOSE]] current = scheduler.reading[current]
--[[VERBOSE]] output:write(" ")
--[[VERBOSE]] output:write(tostring(self.labels[current]))
--[[VERBOSE]] end
--[[VERBOSE]]
--[[VERBOSE]] output:write(newline)
--[[VERBOSE]] output:write("Writing:")
--[[VERBOSE]] for _, current in ipairs(scheduler.writing) do
--[[VERBOSE]] current = scheduler.writing[current]
--[[VERBOSE]] output:write(" ")
--[[VERBOSE]] output:write(tostring(self.labels[current]))
--[[VERBOSE]] end
--[[VERBOSE]] end
--[[VERBOSE]] end