This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
Slight Change to The parallel API
Started by Imred Gemu, 15 September 2015 - 04:01 AMPosted 15 September 2015 - 06:01 AM
So I've been working on this project for the past couple of weeks, and I needed to override the os.pullEventRaw function to modify some events as they're being pulled. This works fine if I'm only working with one coroutine, but I needed to run several coroutines side by side with the parallel API. Because the parallel API uses pullEventRaw, this resulted in some weird behavior. I ended up having to override the parallel API itself to make it use coroutine.yield directly instead. What I'm suggesting is that it should do that by default. Most programs don't use coroutine.yield to pull events, so overriding pullEventRaw is good enough. Having the parallel API run below that with coroutine.yield will prevent issues like what I was having.
Posted 15 September 2015 - 07:06 AM
os.pullEventRaw is just a wrapper for coroutine.yield. I don't really understand what your problem is/was.
Posted 15 September 2015 - 07:51 AM
Let's say you've got a coroutine being handled by the parallel API. It tries to pull an event the usual way, which results in os.pullEventRaw() being called. That tries to get an event from the parallel API, which also calls os.pullEventRaw() as it goes off to fetch it. The API gets its event, modifies it due to the override, then passes it to the coroutine, where the original os.pullEventRaw() call modifies it again before finally returning it.
If the parallel API called coroutine.yield() directly then the event would only be modified by os.pullEventRaw() once per coroutine. Well, assuming the coroutines don't call coroutine.yield() directly, in which case the events won't be modified at all…
It strikes me that you could use a recording system to track whether a given event has already been changed, and hence doesn't need to be changed again - rednet.run()'s "tReceivedMessages" table comes to mind. Granted, that's more complex to do, but it'd allow you to override coroutine.yield() itself and thereby prevent any bypassing.
While we're on the topic, though, I wouldn't mind a "parallel.waitForFirst(first, …)"…
If the parallel API called coroutine.yield() directly then the event would only be modified by os.pullEventRaw() once per coroutine. Well, assuming the coroutines don't call coroutine.yield() directly, in which case the events won't be modified at all…
It strikes me that you could use a recording system to track whether a given event has already been changed, and hence doesn't need to be changed again - rednet.run()'s "tReceivedMessages" table comes to mind. Granted, that's more complex to do, but it'd allow you to override coroutine.yield() itself and thereby prevent any bypassing.
While we're on the topic, though, I wouldn't mind a "parallel.waitForFirst(first, …)"…
Posted 15 September 2015 - 08:26 AM
Couldn't you modify coroutine.yield then?
Like this:
Like this:
local f1 = function()
-- do some stuff here
end
local env = {}
env.coroutine = setmetatable({},{__index=_G.coroutine})
env.coroutine.yield = function(...)
-- maybe return something here, i guess
end
env = setmetatable(env, {__index=_G})
setfenv(f1,env)
-- add more functions/environments here
parallel.waitForAny(f1,f2,..)
Posted 15 September 2015 - 09:14 AM
Yep, that's another option.
Posted 15 September 2015 - 05:37 PM
Bomb Bloke explained it better than I can. I hadn't thought of this but unfortunately overriding the parallel API in my program doesn't work either as, kind of a duh thing looking at it now, my program will never be the first coroutine being run on that computer. Even the entire computer is running in a coroutine since Luaj can't handle true multithreading, and it seems that the java side that implements the paralleling of every computer in the game uses the individual computer's os.pullEventRaw (Basing this off some testing I've done, I haven't actually dug into the code to check). I'm trying to avoid overriding yield, I still want other programs to be able to access that actual raw event data if they need to. I'm gonna try something else, if it work's I'll post it here.os.pullEventRaw is just a wrapper for coroutine.yield. I don't really understand what your problem is/was.
Posted 15 September 2015 - 07:31 PM
Bomb Bloke explained it better than I can. I hadn't thought of this but unfortunately overriding the parallel API in my program doesn't work either as, kind of a duh thing looking at it now, my program will never be the first coroutine being run on that computer. Even the entire computer is running in a coroutine since Luaj can't handle true multithreading, and it seems that the java side that implements the paralleling of every computer in the game uses the individual computer's os.pullEventRaw (Basing this off some testing I've done, I haven't actually dug into the code to check). I'm trying to avoid overriding yield, I still want other programs to be able to access that actual raw event data if they need to. I'm gonna try something else, if it work's I'll post it here.os.pullEventRaw is just a wrapper for coroutine.yield. I don't really understand what your problem is/was.
When overriding yield the way I did in my other post it will be just changed for specific functions.
Posted 16 September 2015 - 12:48 AM
I know, but I need the change to effect the entire computer.When overriding yield the way I did in my other post it will be just changed for specific functions.
Posted 18 September 2015 - 04:55 AM
I still maintain that this issue should be addressed in the parallel API, but in the mean time I need to find a work around. I'm going to take that up on Ask A Pro: http://www.computercraft.info/forums2/index.php?/topic/24674-overriding-the-event-system/