This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

StateMachine API

Started by KingofGamesYami, 28 January 2016 - 10:50 PM
KingofGamesYami #1
Posted 28 January 2016 - 11:50 PM
Many people have heard of multitasking, or running multiple things at once. Well, my API takes a different look at multitasking - that of the statemachine. With a state machine, you do not use any blocking commands (sleep, os.pullEvent, etc.). Instead, you use entirely Asynchronous commands, which allows you to (potentially) do many things at the same time.

The basic usage of my API is somewhat simple:


os.loadAPI( "statemachine" )
statemachine.setLoop( function()
  print( "An event occurred!" )
end )
statemachine.run()

…however, there is more to it than that. My API includes it's own pullEvent, which means you can do this:


os.loadAPI( "statemachine" )
statemachine.setLoop( function()
  local event = {statemachine.pullEvent()}
  print( "An event of the type " .. event[ 1 ] .. " has occurred!" )
end )
statemachine.run()

Unfortunately, many functions commonly used are blocking (eg turtle.forward). You can use them with my API, but you must first convert them to a non-blcoking command via the unblock function.


local async_forward = statemachine.unblock( turtle.forward )

It is important to note that a blocking command will return true when it is complete, with any values returned by the function afterward.


--#using async_forward
os.loadAPI( "statemachine" )
statemachine.setLoop( function()
  local complete, success = async_forward()
  if complete and success then
    print( "The turtle moved forward!" )
  end
end )
statemachine.run()
In this example, the turtle will (try to) move forward forever, and each time it completes a movement it will execute the print statement.

Another important bit of usage to note is the ability to end your program. To end your program simply add a return true.

This example will print all events that occur for 10 seconds, then end the program

os.loadAPI( "statemachine" )
local usleep = statemachine.unblock( sleep )
statemachine.setLoop( function()
  local event = {statemachine.pullEvent()}
  print( event[ 1 ] )
  if usleep( 10 ) then --#after 10 seconds
    return true --#end the program
  end
end )
statemachine.run()

The API can be found here:

pastebin get 3qe1iUQc

Please comment with any bugs or features you want removed or added, respectively.
Lignum #2
Posted 29 January 2016 - 12:33 AM
This looks very nice! If I recall correctly, the native turtle functions do not block. So by calling turtle.native().forward() instead of turtle.forward(), you should be able to avoid using statemachine.unblock. I haven't tested this though.
oeed #3
Posted 29 January 2016 - 12:40 AM
This looks very nice! If I recall correctly, the native turtle functions do not block. So by calling turtle.native().forward() instead of turtle.forward(), you should be able to avoid using statemachine.unblock. I haven't tested this though.

How long has turtle.native() been a thing? Are you sure you're not confusing term.native()? It seems like a strange thing to have a 'native' for turtle.
CometWolf #4
Posted 29 January 2016 - 12:46 AM
turtle.native used to be a table pointing to the raw java side functions. It was replaced with a table that's essentially the same as turtle over a year ago. As Lignum stated, these did indeed not block and were quite useful…
http://www.computerc...rtle-functions/
Edited on 28 January 2016 - 11:47 PM
Bomb Bloke #5
Posted 29 January 2016 - 02:12 AM
Indeed, turtle.native functions block now. They used to act as commands.execAsync() does, but now act like commands.exec() (because as Comet points out, the function pointers in turtle.native are now identical to those in the base turtle table).

I don't believe Dan ever explained why he decided to change them.