4 posts
Posted 08 July 2013 - 07:08 PM
http://pastebin.com/Q0zEx27mI wrote this program to turn on my backup generators when my batteries (MFSUs and AESUs) start running low. My main power is solar. The computer sits next to an eu-splitter.
I recently figured out how to use parallel to capture keyboard events without pausing the whole program. So far I have 4 commands. 3 of the commands work great, but when I run the re-scan the computer shuts off after findTargets seems to finish. It doesn't throw any errors, just shuts off. Is there a better way to pause main while findTargets is running?
I am running this on an advanced computer.
CC 1.53pr3
OCS 1.5.2.0
Forge 7.8.0.734
8543 posts
Posted 08 July 2013 - 08:11 PM
Split into new topic.
4 posts
Posted 08 July 2013 - 08:23 PM
Thank you Lyqyd.
871 posts
Posted 08 July 2013 - 08:36 PM
You're using parallel.waitForAny, so it will quit when either coroutine quits, and in general parallel eats errors, so it's probably an error in your findTargets function.
At a guess, it could be erroring when you call comma_value, which is not defined yet; try defining it first. Failing that, or just for future reference, try testing the functions separately where possible, so you can see the errors while debugging. If you can't test without using parallel because of interactions between the functions being required, wrap them when passing to parallel with an anonymous function that uses pcall and prints the error. Example code to help show/explain:
--this guy errors out if a key is hit
function a()
os.pullEvent("key")
error("got key event ")
end
--this one just errors after 15 seconds
function b()
sleep(15)
error("15 secs are up!")
end
--calling like this will suppress the error in either case
print("calling parallel with naked functions...")
parallel.waitForAny(a,b)
--this will wrap a function so it is pcall-ed, catching and displaying any error
function wrapPcall(f)
return function()
local succ,err=pcall(f)
if not succ then
print(err)
end
end
end
--use that to wrap the args to parallel will make the errors display.
print("calling parallel with wrapped functions...")
parallel.waitForAny(wrap(a),wrap(b))
I shouldn't be posting this since I have no way of testing it, so it almost certainly has errors… Someone who can, assist pls?
375 posts
Location
USA
Posted 08 July 2013 - 08:44 PM
This is what I think is happening: When you set pause to true in your commands thread, your main thread ends. You are using parallel.waitForAny, which continues after any of the threads die. On the sleep call on line 94, the commands thread yields and will never get back to its original state because the main thread will always kill itself. Using parallel.waitForAll should fix your problem, I think. If you use parallel.waitForAll, you can also get rid of the surrounding while loop.
@GopherAtl Actually his comma_value function is defined by that point because it is global.
871 posts
Posted 08 July 2013 - 08:52 PM
Could happen, yevano, but only if th 4-second sleep timer goes off at exactly the right moment, which it shouldn't, at least not more than 1 time in 4.
Though looking again, I notice that command() ALWAYS exits after a single char event, whether it's a valid command or not, because it doesn't loop. It should be in a "while true do" loop, or possibly "while run do"?
:edit: re: the function being global, in my experience cc+luaj seem … Inconsistent… In the rules on this sort of thing. This may just be my failure to grasp the full set of rules, though…
101 posts
Location
Norway
Posted 08 July 2013 - 09:18 PM
why doesn't you just add the findTargets() into the main program?? then it will auto update if you're adding or removing anything.
function main()
findTargets()
if pause == false then
or you can just remove your while loop and add this
timeout = os.startTimer(1)
while run == true do
main()
event2 = {os.pullEvent()}
if event2[1] == "key" then
commands()
break
elseif event2[1] == "timer" and event2[2] == timeout then
timeout = os.startTimer(1)
end
sleep(1)
end
i think this should work but correct me if i'm wrong
101 posts
Location
Norway
Posted 09 July 2013 - 12:16 AM
i'm going to try this out tomorrow and upload a pastebin if i can get it to work ;)/>
stay tuned..
4 posts
Posted 09 July 2013 - 02:10 AM
Thank you all for your responses! I will try your suggestions soon. The reason I don't have findTargets in the main thread is because it is slow. It takes a few seconds to run. I am trying to be nice to the server CPU.
4 posts
Posted 09 July 2013 - 03:28 AM
MR_nesquick: I tried your suggestion, but it still locks up the program waiting for events.
GopherAtl: Wrapping the functions sounds like a good idea, but your example confused me. For example, you define a function called "wrapPcall", but call "wrap". I got my program to work without it, but I would like to implement it in the future.
Yevano: I think you were right about parallel.waitForAny().
I updated the paste with the code that now works
I gave main() and commands() their own while loops.
It turns out that running findTargets() while main() is using those targets doesn't cause catastrophe like I thought it would. The worst thing that happens is main() uses an incomplete targets{}, causing it to show low numbers which always turns on the generators. I put an if checking for pause over the redstone switching if's so the generators don't kick on just because you re-scanned.
Tomorrow's Project: look into making it so removing a battery doesn't cause it to try to call nil. Also, implement GopherAtl's wrap suggestion to make future debugging easier.
871 posts
Posted 09 July 2013 - 08:49 AM
Whoops, I changed the name at the last minute and didn't fix that, sorry. Like I said at the end of the post, couldn't actually test-run it like I normally would - on an iPad ATM.