4 posts
Posted 03 September 2013 - 10:26 AM
Whilst debugging some event driven code, I found that my timer events were sporadically disappearing. I traced the problem to the gps.locate() function. I've recreated the issue with a much smaller program here:
t = os.startTimer(1)
print(t)
os.sleep(2)
gps.locate(2, true)
while true do
e, p = os.pullEvent()
print(string.format("%s: %s", e, p))
if p == t then break end
end
gps.locate() calls os.pullEvent() and discards events it's not interested in.
Should I raise this as a bug?
8543 posts
Posted 03 September 2013 - 01:31 PM
Split into new topic.
This isn't a bug.
Regardless of whether or not gps.locate eats your timer events, in that code, you start a one-second timer, then sleep for two seconds, which means that your timer event has already fired and disappeared before you even call gps.locate.
gps.locate does, in fact, eat other events, just like sleep, read, rednet.receive, and the turtle functions. If you need to prevent it from eating your events, you could run it in a coroutine controlled by your program. Bear in mind that if this is for a turtle, your turtle function calls will eat events too.
4 posts
Posted 04 September 2013 - 05:56 AM
Thanks for your feedback - really helpful.
My example was a bit trivial - I didn't want to paste my entire program because I wanted to try and illustrate the problem I'm having. Here's a (still trivial) but slightly more realistic example.
My turtle starts two timers. One for moving and one for working (the application is a farm where the turtle wanders around randomly harvesting and sowing). This code roughly approximates this:
function move()
gps.locate(2, false)
print("move()")
end
function work()
print("work()")
end
m = os.startTimer(1)
w = os.startTimer(5)
while true do
e, p = os.pullEvent()
if p == m then
move()
m = os.startTimer(1)
elseif p == w then
work()
w = os.startTimer(5)
end
end
At some point, the work timer event gets grabbed (and discarded) in gps.locate() and so my work() function never gets called again. It would be nice if the ROM programs/apis could requeue events which they are not interested in.
Interesting what you say about coroutines - do coroutines maintain separate event queues?
7508 posts
Location
Australia
Posted 04 September 2013 - 06:05 AM
It would be nice if the ROM programs/apis could requeue events which they are not interested in.
This is very, very, very, problematic to do this (also very difficult to do accurately), how they function is correct and they should not function any differently.
Interesting what you say about coroutines - do coroutines maintain separate event queues?
Yes, when using the
Parallel API each coroutine is supplied with the event, meaning that each routine will receive the event. However if you do coroutines manually you will have to be in charge of making sure that each coroutine gets the event, it is not automatically done for you.
EDIT: As Lyqyd stated the some functions consume events, here is a list of all the ones that I can think of off the top of my head that consume events:
- sleep/os.sleep
- read/io.read
- turtle functions
- rednet.receive
- gps.locate (as you know)
- http functions
and the reason that they do is because they are all looking for a particular event and make use of
os.pullEvent/
os.pullEventRaw/
coroutine.yield which grabs an event from the event queue for them.
Edited on 04 September 2013 - 04:12 AM
4 posts
Posted 04 September 2013 - 06:14 AM
Thanks.
Probably worth mentioning in the Wiki somewhere that event delivery is not reliable by design. I guess Minecraft is a game after all :)/>
7508 posts
Location
Australia
Posted 04 September 2013 - 06:31 AM
Probably worth mentioning in the Wiki somewhere that event delivery is not reliable by design. I guess Minecraft is a game after all :)/>
I think it does in the
os.pullEvent thread. Also it should be stated that it is reliable as possible, it cannot become anymore reliable than it is.