How are coroutines used in Lua

Lua: for beginners

Beginnings

Advanced

Lua functions

miscellaneous

Use Lua in C.

Left


We dedicate an extra chapter to the coroutines because everything belongs together.

A coroutine is a special type of function. You can convert any function into a coroutine. The examples are very important to understand.
We are used to one function working one by one until the end is reached.
A coroutine does that too, only with one huge difference.
You can stop it and at some point let it run again. All variables that have been worked out up to that point are retained. The function continues at this point as if nothing had happened. (If it is triggered again)

Examples come at the end, as this can only be understood in context.
The functions for coroutines are in the table

coroutine

saved.

coroutine.create (f)
coroutine.resume (co, val1, ...)
coroutine.status (co)
coroutine.wrap (f)
coroutine.yield (val1, ...)

Coroutine example 1
Coroutine example 2
Coroutine example 3
Coroutine example 4






This function creates a coroutine.

The following is to be transferred as a parameter:
  • The function that is supposed to work as a coroutine.
The return is a variable of the type "thread" (a separate type to carry out these coroutines)

myRoutine = coroutine.create (PrintSomething) - The coroutine
- is generated, but it doesn't do anything yet. It must first be initiated



This function runs a coroutine. (Nudges her)

The following is to be transferred as a parameter:
  • The variable that was returned when the coroutine was created.

The parameters are only accepted the first time the resume function is called. They are ignored for each subsequent one.

The return is on the one hand the status of the function and on the other hand the parameters that are returned when the function is stopped

status, val1, ... = coroutine.resume (myRoutine, 50)
- The coroutine is started. A parameter (here 50) is passed to it.


The status is true if the function ran without an error.
Val1, ... are either the values ​​that are transferred when the function is stopped or the values ​​that are transferred when the function is terminated.




This function returns the current status of the coroutine as a string.

The following is to be transferred as a parameter:
The variable that was returned when the coroutine was created.


result = coroutine.status (myRoutine)

result can have three states.

  • "running" the function is running
  • "suspended" the function is on leave
  • "dead" the function has ended
"dead" occurs with normal termination or with termination due to an error.




This function also creates a coroutine. However, the traffic jam cannot be queried here.

The following is to be transferred as a parameter:

The return is a variable of the type "function"

myCallFunction = coroutine.wrap (PrintSomething)
- The coroutine is generated

myCallFunction returns either the values ​​that are passed when the function is stopped or the values ​​that are passed when the function terminates. The parameters that you want to transfer are given as parameters.


Value = myCallFunction (50)







This function stops a coroutine. Therefore it has to be within the function.

The following is to be transferred as a parameter:
  • The values ​​that you want to return to resume or the calling function.
Returns none.

coroutine.yield (1000)


The function (coroutine) is stopped and the value 1000 is transferred to the call function






function UeberwacheRoutine ()
if value + beginnRoutine <= os.clock () * 1000then
coroutine.resume (myRoutine)
- here the coroutine is for the second time
- started. There no longer has to be a parameter
- he would be ignored like that
return true
end
end

function PrintSomething (_how much)
print (_how much)
print ("Status3 =" ..coroutine.status (myRoutine))
coroutine.yield (1000) - stop
_how much = _how much - 1
print (_how much)
end

beginningRoutine = os.clock () * 1000
- Start time in 1000ths of a second
myRoutine = coroutine.create (PrintSomething)
- The coroutine is generated

print ("Status1 =" ..coroutine.status (myRoutine))

status, value = coroutine.resume (myRoutine, 50)
- The coroutine is started for the first time. a parameter
- (here 50) will be handed over to you

print ("Status2 =" ..coroutine.status (myRoutine))

whilenot UeberwacheRoutine () doend
- as long as the function does not return true, it always will
- executed again

print ("Status4 =" ..coroutine.status (myRoutine))



Procedure example 1:


  • The computer reads the two functions in sequence.
  • Then it saves the time in the variable beginnRoutine
  • The coroutine is created and the thread is stored in the variable myRoutine
  • The current status of the coroutine is printed out. Since it is not yet running, the result is suspended
  • We start the routine and pass it the parameter 50
  • The routine prints the value 50.
  • The routine prints out its status: running. (she is running)
  • The routine stops and passes true and 1000 to resume
  • true is stored in the status variable and 1000 in the value variable
  • The current status of the coroutine is printed out. Since it is no longer running, the result is suspended
  • Then it goes into a loop that executes the function UeberwacheRoutine until it has a value that is not equal to
    returns nil or false
  • The function continuously checks whether the start time has increased by the value 1000. (1 second) Is that the case,
    so it goes in the block.
  • The coroutine is then started for the second time in the block and continues after yield
  • There, 1 is deducted from our parameter and then printed out.
  • The function ends.
  • The UeberwacheRoutine function ends with the fact that it returns the value true.
  • This means that the condition for the while loop is false and it ends.
  • The current status of the coroutine is printed out. Since it has ended, the result is dead.





function UeberwacheRoutine ()
if value + beginnRoutine <= os.clock () * 1000then
beginningRoutine = os.clock () * 1000
status, value = coroutine.resume (myRoutine, 50)
end
end

function PrintSomething (_how much)
for i = 1, 10do
print (_how much)
coroutine.yield (1000)
_how much = _how much - 1
end
return "I'm done"
end

beginnRoutine = os.clock () * 1000
myRoutine = coroutine.create (PrintSomething)
status, value = coroutine.resume (myRoutine, 50)
time = os.clock () * 1000

while coroutine.status (myRoutine) ~ = "dead" do
MonitorRoutine ()
end
print (value)

If that is understood above, things are a little easier here.

Except for the loop, it looks pretty much the same at first.

  • The coroutine starts, runs in the for loop, prints out and stops.
  • The 1000 are again stored in value. The next loop runs until the coroutine has the status "dead",
    so ended.
  • If the second is up, the new time is saved in the variable beginnRoutine.
  • The routine is started again.
  • Subtracts 1 from how much and prints it out.
  • Stop again. Return is 1000 again
  • The first function now monitors whether the next second has passed.
  • The whole thing continues until the for loop is finished
  • Then it prints out "I'm done"





function UeberwacheRoutine ()
if value + beginnRoutine <= os.clock () * 1000then
myCallFunction ()
- here the coroutine is for the second time
- started. There no longer has to be a parameter
- he would be ignored anyway
return true
end
end

function PrintSomething (_how much)
print (_how much)
coroutine.yield (700)
_how much = _how much - 1
print (_how much)
end

beginnRoutine = os.clock () * 1000
- Start time in 1000ths of a second
myCallFunction = coroutine.wrap (PrintSomething)
- The coroutine is generated

value = myCallFunction (50)
- The coroutine is started for the first time. a parameter
- (here 50) will be handed over to you

whilenot UeberwacheRoutine () doend
- as long as the function does not return true it always will
- executed again


Similar to example 1 the differences:

1. Once the type of call and then,
2. that we cannot query any status.








function UeberwacheRoutine ()
if value + beginnRoutine <= os.clock () * 1000then
beginningRoutine = os.clock () * 1000
value = myCallFunction ()
end
end

function PrintSomething (_how much)
for i = 1, 10do
print (_how much)
coroutine.yield (50)
_how much = _how much - 1
end
return -1
end

beginnRoutine = os.clock () * 1000
myCallFunction = coroutine.wrap (PrintSomething) - The coroutine is generated and the resum function is saved

value = myCallFunction (50) - The coroutine is started for the first time. A parameter (here 50) is passed to it

while value ~ = -1do
MonitorRoutine ()
end


The difference to example 2: You have to come up with something to find out whether the function has ended. (here I return -1)

You can't query it

The reproduction of the information and graphics contained on these pages is prohibited, with the exception of all source code displayed on these pages.
See also: disclaimer
Copyright © Robert Schmitz 2006