Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Due to spam on this forum, all posts now need moderator approval.
Entire forum
➜ MUSHclient
➜ Lua
➜ Control Loop not behaving correctly
Control Loop not behaving correctly
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Posted by
| Tharius
(29 posts) Bio
|
Date
| Fri 16 Oct 2015 02:47 PM (UTC) Amended on Mon 19 Oct 2015 01:35 AM (UTC) by Tharius
|
Message
| Hi everyone,
I have borrowed from my industrial experience and created a control loop to control one of my bots. I can probably just put this into a loop but I chose to make it a tail call since there's no penalty for that in Lua.
I have also asked this question on http://stackoverflow.com/q/33161999/759749 but in the event that it is not Lua, but an interaction with Mushclient that is causing the problem I thought I'd post here.
In essence the idea is that on login I call my control function and it runs continuously until the character logs out. In between I can manually run commands or other triggers may be processed. I want it to run about every 10 seconds but unlike just calling this from an alarm I get a guarantee that I will not have multiple simultaneous instances running if some command hangs.
function myFunc ()
-- do some stuff
-- lots of snazzy logic and function calls
-- heck, throw in a few prints
print "Going to sleep"
-- sleep for a bit
os.execute("sleep 10")
print "Waking up"
-- tail call
return myFunc()
end
What happens now is that the system becomes utterly unresponsive and no output is produced. I'm looking for a blocking/non-busy wait for the sleep function and also an io flush for world.send or world.note
Thanks | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #1 on Fri 16 Oct 2015 08:55 PM (UTC) |
Message
| |
Posted by
| Tharius
(29 posts) Bio
|
Date
| Reply #2 on Sat 17 Oct 2015 08:30 PM (UTC) Amended on Mon 19 Oct 2015 01:26 AM (UTC) by Tharius
|
Message
| Hi Nick, yes your wait thread was a very welcome reminder and does solve _some_ of the problem for sure.
I am having some difficulty with the tail call at the end with this wait code.
Example:
function controlLoop()
wait.make (
function()
world.Note("Hello world.")
wait.time(10)
end
)
world.Note("Goodbye world.")
return controlLoop()
end
Should have the sequence: Hello, wait, goodbye, tail call, hello, wait, goodbye ... in perpetuity.
What I observe is that this causes a tight infinite loop that takes up 100% of CPU resource and causes Mush to become inactive.
Try 2 right?
function controlLoop()
wait.make (
function()
world.Note("Hello world.")
wait.time(10)
world.Note("Goodbye world.")
return controlLoop()
end
)
end
Running the above small code example does not seem to allocate any new memory, and seems to correctly implement a tail call (I am concerned about the end)end but I'm guessing Lua has it figured out...
Adapting this to my full version resulted in the following error but I am now going to check if I accidentally allowed a tight loop on one condition branch and see what changes.
Quote:
Error raised in timer function (in wait module).
stack traceback:
[C]: ?
...MUD\MUSHclient\lua\wait.lua:178: in function 'make'
[string "Script file"]:29: in function <[string "Script file"]:27>
(tail call): ?
Run-time error
World: BrewRoomBot
Function/Sub: wait.timer_resume called by timer
Reason: processing timer "wait_timer_241"
...MUD\MUSHclient\lua\wait.lua:51: ...MUD\MUSHclient\lua\wait.lua:178: [times 175 repeats]
...MUD\MUSHclient\lua\wait.lua:178: C stack overflow
stack traceback:
[C]: in function 'error'
...MUDMUSHclientluawait.lua:51: in function <...MUDMUSHclientluawait.lua:43>
Thanks Nick | Top |
|
Posted by
| Tharius
(29 posts) Bio
|
Date
| Reply #3 on Sat 17 Oct 2015 08:40 PM (UTC) |
Message
| I threw a wait.time(1) unconditionally before the tail call and a wait.time(10) only on the branch that returns the state to the initial loop and all is well with the world.
Putting an unconditional tail call simply made the thing cycle too quickly. | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #4 on Sun 18 Oct 2015 08:57 PM (UTC) |
Message
|
function controlLoop()
wait.make (
function()
world.Note("Hello world.")
wait.time(10)
end
)
world.Note("Goodbye world.")
controlLoop()
end
That is recursion. I'm not surprised it hung.
function controlLoop()
wait.make (
function()
world.Note("Hello world.")
wait.time(10)
world.Note("Goodbye world.")
controlLoop()
end
)
end
Likewise. How about a real loop?
This works without hanging or gobbling up CPU:
require "wait"
function controlLoop()
wait.make (
function()
while true do
world.Note("Hello world.")
wait.time(10)
world.Note("Goodbye world.")
end -- loop
end
)
end
controlLoop ()
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Tharius
(29 posts) Bio
|
Date
| Reply #5 on Mon 19 Oct 2015 01:31 AM (UTC) Amended on Mon 19 Oct 2015 01:36 AM (UTC) by Tharius
|
Message
| A minor edit to my code post to reflect what I actually ran: the recursive call to "controlLoop()" was in fact a tail call "return controlLoop()", bad transposition on my case.
Your real loop is far too simple and makes far far too much sense.... errr uhm... I don't want to indent one level ... or ... yes, something!
The 2nd version where I correctly use the tail call works exactly as I expect it to ... I'm going to chalk this up to programmeritis and a bit of tunnel vision. I suppose I figured there was an advantage to actually having the function exit from a time slicing or multitasking point of view, but the wait functionality is giving all the performance in the world back to the system.
The final working version (aside from Nick's completely obvious and perfectly functional loop version :-)
function controlLoop()
wait.make (
function()
world.Note("Hello world.")
wait.time(10)
world.Note("Goodbye world.")
wait.time(1)
return controlLoop()
end
)
end
P.S. Now that it works I'll probably rewrite it as the simpler and more understandable loop. Thanks for breaking the tunnel vision. | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #6 on Mon 19 Oct 2015 05:03 AM (UTC) |
Message
| You are relying on the tail recursion working there. Personally I would use the loop. Effectively you are looping anyway. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Nick Gammon
Australia (23,133 posts) Bio
Forum Administrator |
Date
| Reply #7 on Mon 19 Oct 2015 05:04 AM (UTC) |
Message
| If you introduce a local variable the tail recursion may fail as it has to preserve the local variable (I think). So if you keep it, you may find it comes back to bite you when you start making it more complex. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Tharius
(29 posts) Bio
|
Date
| Reply #8 on Mon 19 Oct 2015 01:54 PM (UTC) |
Message
| I write all local variables back to mush variables so they can be preserved across sessions but of course by rewriting it into a loop we have the opportunity to simplify that.
Thanks again Nick | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
23,552 views.
It is now over 60 days since the last post. This thread is closed.
Refresh page
top