Coroutines

The coroutine library

by Halalaluyafail3

Author Avatar

The coroutine library is used for all manipulations of coroutines.

Coroutines are pseudo threads, used to have multiple tasks run at once, but not really. They are useful to have multiple things happen at once. For instance, to get task x to happen every second, and task y to happen every 2.5 seconds; a loop can be used with both x and y, but this gets very excessive when there is more than 2 tasks happening. Using coroutines makes this very simple, even with 25 tasks.

coroutine.create(function f)

Creates a new coroutine (a thread) with body f, and returns it. In 5.1 (what roblox uses), f cannot be a C function (e.g print), but this is fixed in newer lua versions.

coroutine.running()

Returns the running thread. In 5.2+ this also returns a boolean of whether the running thread is the main one. In 5.1, returns nil if the thread is the main thread.

coroutine.isyieldable()

Returns whether the running thread can yield. (Roblox backported this, but it is in 5.3+)

coroutine.yield(...)

Yields the running thread. If the thread is unable to yield, this function errors. Any arguments to yield are passed as extra results to resume. (see below) Returns all values provided the next time the thread is resumed.

coroutine.resume(thread co,...)

Resumes thread co. The first time co is resumed, all extra arguments to resume are provided as paramters to the body function of co. If co has yielded, resume restarts it; all extra arguments are passed as results from the yield.

If co runs without errors, resume returns true plus all any values passed to yield or any values returned by the body function (when the thread terminates). If co errors, then resume returns false plus the error message.

coroutine.status(thread co)

Returns the status of co, as a string: "running", if the co is the running thread; "suspended", if co is suspended in a call to yield, or if co has not started yet; "normal", if co is active, but not running (it has resumed another thread); "dead", if co has finished its body function, or if it has stopped with an error.

coroutine.wrap(function f)

Creates a coroutine with body f. In 5.1 (what roblox uses), f cannot be a C function (e.g print), but this is fixed in newer lua versions. Returns a function that resumes the thread each time called. Any arguments passed to the function behave as extra arguments to resume. Returns the same values as returned by resume, except the first boolean. In case of error, propagates the error.

Examples

local function body(x)
    print("THREAD:",x)
    print("THREAD:",coroutine.yield(2))
    return 4
end
local thread = coroutine.create(body)
print("MAIN:",coroutine.resume(thread,1))
print("MAIN:",coroutine.resume(thread,3))
-- output
--> THREAD: 1
--> MAIN: true 2
--> THREAD: 3
--> MAIN: true 4
local thread = coroutine.wrap(function(x)
    print(x)
    coroutine.yield()
    return "b"
end)
thread"a"
print(thread())
local function canyield()
    print(coroutine.isyieldable())
    return ""
end
local tbl = setmetatable({},{__tostring=canyield})
tostring(tbl)
-- __tostring can't yield, even in newer lua versions which allow yielding in metamethods

-- output
--> a
--> b
--> false
local thread2
local thread = coroutine.create(function()
    print(coroutine.status(coroutine.running()))
    coroutine.yield(coroutine.resume(thread2))
end)
thread2 = coroutine.create(function()
    print(coroutine.status(thread))
end)
coroutine.resume(thread)
print(coroutine.status(thread))
coroutine.resume(thread)
print(coroutine.status(thread))
-- output
--> running
--> normal
--> suspended
--> dead

View in-game to comment, award, and more!