2679 posts
Location
You will never find me, muhahahahahaha
Posted 04 March 2015 - 06:50 PM
About coroutines, I have written this code:
Spoiler
--Kernel--
--Variables--
local routines = {}
local arguments = {}
local args = {...}
local _funcPath = args[1]
local _title = args[2]
table.remove(args,2)
table.remove(args,1)
--Functions--
function getPermission(base,program)
local f = fs.open(base.."/"..program..".permission")
local m = f.readAll()
f.close()
return m
end
function newProcess(funcPath,title,_arguments)
local routineIsPresent = false
local func
local buffer = {}
local permission = nil
local base = ""
local program = nil
local environement = {}
routines[title] = ""
for i,v in pairs(routines) do
if i == title then
routineIsPresent = true
end
end
if routineIsPresent then return false end
if type(funcPath) == "string" then
func = loadfile(funcPath)
else return false end
for token in string.gmatch(funcPath,"(/[^/]+)") do
buffer[#buffer+1] = token
end
for i = 1, #buffer-1 do
base = base..buffer[i]
end
program = buffer[#buffer]
if buffer[#buffer-2] == "Programs" then
permission = getPermission(base,program)
environement = Sandbox.newEnvironement(funcPath,permission)
else
setmetatable(environement,{_index = _G})
end
routines[title] = coroutine.create(func)
arguments[title] = unpack(_arguments)
end
function coroutineManager()
while true do
for i,v in pairs(routines) do
print(v)
os.pullEvent()
coroutine.resume(v,arguments[i])
end
end
end
newProcess(_funcPath,_title,_arguments)
for i,v in pairs(routines) do
print(i)
end
os.pullEvent()
coroutineManager()
And it throws an error at line 60
coroutine.resume(v,arguments[i])
So I don't get what is wrong and I am sure that if we try to fix this here together, DannySMc could benefit from this too.
PS: I did not want to start another topic that discusses the exaclty same thing and I read through the tutorial and many other tutorials and inclusively looked at multishell. If you want to look at the code here it is:
TheOS.
Thanks in advance and I hope we can help the comunity!
~Creator
8543 posts
Posted 04 March 2015 - 07:55 PM
Split into new topic.
Obviously, you can both read each other's topic as they progress, but it will be much easier for those helping to track what's going on with the two separate people having their own topic.
2679 posts
Location
You will never find me, muhahahahahaha
Posted 04 March 2015 - 07:59 PM
Split into new topic.
Obviously, you can both read each other's topic as they progress, but it will be much easier for those helping to track what's going on with the two separate people having their own topic.
Thanks, I guess you are right in some way. But that does still not answer my question. ;)/>
7083 posts
Location
Tasmania (AU)
Posted 04 March 2015 - 09:42 PM
You neglected to mention the content of your error. But at a glance:
arguments[title] = unpack(_arguments)
"_arguments" will always be nil, and even if it
were a suitable table, this would do the same thing:
arguments[title] = _arguments[1]
Generally, one would want to resume coroutines with event data, however.
2679 posts
Location
You will never find me, muhahahahahaha
Posted 04 March 2015 - 10:00 PM
You neglected to mention the content of your error. But at a glance:
arguments[title] = unpack(_arguments)
"_arguments" will always be nil, and even if it
were a suitable table, this would do the same thing:
arguments[title] = _arguments[1]
Generally, one would want to resume coroutines with event data, however.
Thanks, however I do not think that is the problem. The error it throws is "Thread expected, got string"
7083 posts
Location
Tasmania (AU)
Posted 04 March 2015 - 11:02 PM
routines[title] = ""
for i,v in pairs(routines) do
if i == title then
routineIsPresent = true
end
end
if routineIsPresent then return false end
This adds an "title" key to your "routines" table, checks to see if it's already in there, then returns false when it inevitably finds that it is. Switch the order around a little.
2679 posts
Location
You will never find me, muhahahahahaha
Posted 05 March 2015 - 01:10 PM
I rewrote the whole kernel and this is the result
--Kernel--
--Variables--
local routines = {}
local currRoutine = nil
local args = {...}
local funcPath = args[1]
local title = args[2]
table.remove(args,2)
table.remove(args,1)
--Functions--
local function getPermission(base,program)
local f = fs.open(base.."/"..program..".permission")
local m = f.readAll()
f.close()
return m
end
local function parsePath(_funcPath)
local buffer = {}
for token in string.gmatch(_funcPath,"[^/]+") do
buffer[#buffer + 1] = token
end
return buffer
end
local function getEnvironment(nTable,_path)
if nTable[#nTable-3] == "Programs" then
local b = fs.open(_path..".permissions")
local tEnv = b.readLine()
b.close()
if tEnv == "admin" then
local mEnv = {}
setmetatable(mEnv,{_index = _G})
return mEnv
else
Sandbox.newEnvironement(_path, "semiadmin")
end
else
local mEnv = {}
setmetatable(mEnv,{_index = _G})
return mEnv
end
end
function newProcess(_funcPath,_title,_arguments)
local path = parsePath(_funcPath)
local env = getEnvironment(path,_funcPath)
for i,v in pairs(routines) do
if v == title then return false end
end
routines[title] = ""
local function toRun()
os.run(env,_funcPath,unpack(_arguments))
end
routines[title] = coroutine.create(toRun)
end
local function coroutineManager()
while true do
os.pullEvent()
for i,v in pairs(routines) do
term.clear()
term.setCursorPos(1,1)
print("Resuming coroutine...")
print(i)
print(v)
os.pullEvent()
coroutine.resume(v)
end
end
end
newProcess(funcPath,title,arguments)
term.clear()
term.setCursorPos(1,1)
print("Booting into multitasking...")
os.pullEvent()
coroutineManager()
It's not working and I can't figure out why.
Any help is appreciated ;)/>
~Creator
3057 posts
Location
United States of America
Posted 05 March 2015 - 02:09 PM
while true do
os.pullEvent() --#discard an event from the queue
for i,v in pairs(routines) do --#loop through the coroutines
term.clear()
term.setCursorPos(1,1)
print("Resuming coroutine...")
print(i)
print(v)
os.pullEvent() --#discard another event
coroutine.resume(v) --#resume the coroutine without passing any event information
end
end
…begin to see the problem?
2679 posts
Location
You will never find me, muhahahahahaha
Posted 05 March 2015 - 02:56 PM
What changes should I apply to the code?
3057 posts
Location
United States of America
Posted 05 March 2015 - 03:15 PM
1. Stop pulling events inside the for loop
2. Actually store the data from events outside the for loop, but inside the while loop
3. Keep track of the returns from coroutine.resume, so you know when to apply a filter to events.
4. Filter events using the data from #3, giving the appropriate events to the coroutine when it resumes.
…
This is just what I got on that particular part of your code
2679 posts
Location
You will never find me, muhahahahahaha
Posted 05 March 2015 - 03:59 PM
1. Stop pulling events inside the for loop
2. Actually store the data from events outside the for loop, but inside the while loop
3. Keep track of the returns from coroutine.resume, so you know when to apply a filter to events.
4. Filter events using the data from #3, giving the appropriate events to the coroutine when it resumes.
…
This is just what I got on that particular part of your code
How do I do the third step and it appears to never resume the coroutine because the desktop app is set to turn the screen purple, but it never happens.
3057 posts
Location
United States of America
Posted 05 March 2015 - 04:08 PM
local tFilters = {}
local eventData = {}
while true do
for n=1,count do
local r = _routines[n]
if r then
if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == "terminate" then
local ok, param = coroutine.resume( r, unpack(eventData) )
if not ok then
error( param, 0 )
else
tFilters[r] = param
end
if coroutine.status( r ) == "dead" then
_routines[n] = nil
living = living - 1
if living <= _limit then
return n
end
end
end
end
end
^^ thats how the parallel api does it.
7083 posts
Location
Tasmania (AU)
Posted 05 March 2015 - 10:13 PM
Though there's a little more to it than that (eg - pulling the event data to pass to the coroutines!). Better to read the original source file and get the full picture.
How do I do the third step and it appears to never resume the coroutine because the desktop app is set to turn the screen purple, but it never happens.
When the desktop app yields, it may be calling coroutine.yield() with a parameter, which it probably intends to be an event filter. For example, it might use "char", "key", "timer", or any of the other event names. coroutine.resume() passes these parameters back to the parent process as return values.
You need to ensure that when your coroutine manager detects such an event, that it passes that event data back to the desktop app when it coroutine.resume()'s it. You also need to ensure that, if an event filter was specified, you don't resume the desktop app until the appropriate event appears in the queue.
If you simply resume the desktop app at any time, it'll likely break it. If you resume the desktop app without ever passing it any event data, it'll most certainly break it.
Edited on 05 March 2015 - 09:14 PM
2679 posts
Location
You will never find me, muhahahahahaha
Posted 05 March 2015 - 10:54 PM
Though there's a little more to it than that (eg - pulling the event data to pass to the coroutines!). Better to read the original source file and get the full picture.
How do I do the third step and it appears to never resume the coroutine because the desktop app is set to turn the screen purple, but it never happens.
When the desktop app yields, it may be calling coroutine.yield() with a parameter, which it probably intends to be an event filter. For example, it might use "char", "key", "timer", or any of the other event names. coroutine.resume() passes these parameters back to the parent process as return values.
You need to ensure that when your coroutine manager detects such an event, that it passes that event data back to the desktop app when it coroutine.resume()'s it. You also need to ensure that, if an event filter was specified, you don't resume the desktop app until the appropriate event appears in the queue.
If you simply resume the desktop app at any time, it'll likely break it. If you resume the desktop app without ever passing it any event data, it'll most certainly break it.
Thanks. It appears to be working now, with only one active process ;)/>