[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  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] Refresh page


Posted by Tharius   (29 posts)  [Biography] 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
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Fri 16 Oct 2015 08:55 PM (UTC)
Message
See: http://www.gammon.com.au/forum/?id=4956

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Tharius   (29 posts)  [Biography] 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
[Go to top] top

Posted by Tharius   (29 posts)  [Biography] 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.
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] 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
[Go to top] top

Posted by Tharius   (29 posts)  [Biography] 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.
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] 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
[Go to top] top

Posted by Nick Gammon   Australia  (22,973 posts)  [Biography] 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
[Go to top] top

Posted by Tharius   (29 posts)  [Biography] 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
[Go to top] 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.


20,424 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]