Thread scheduler

(Redirected from Thread)
CodeStub.png
This page is a stub. If you think you know more about this than we do, please help us by contacting a writer.
Thank you!


Roblox uses a thread scheduler to allow multiple scripts to execute in parallel. You can use this to your advantage to run two pieces of code in parallel in the same script. Roblox's thread scheduler is exposed through the functions Spawn, Wait, and Delay.

For the rest of this article, the word "Task" is used to refer to a coroutine being managed by the thread scheduler.

Queueing tasks[edit]

There are two ways to queue tasks into the thread scheduler:

spawn(function()
    print("Spawn - started")
    wait(2)
    print("Spawn - working")
    wait(1)
    print("Spawn - done")
end)
delay(1, function()
    print("Delay - started")
    wait(2)
    print("Delay - working")
    wait(2)
    print("Delay - done")
end)

Task switching[edit]

When roblox runs a wait function (or any other YieldFunction), it pauses the current task, queues it up for later, then looks for other waiting tasks (ie another script, or an event handler), and resumes the next most important. There is no other way to switch task - if you've queued a task with Spawn, you have to wait() in order to make it run:

print("Main task")
 
-- Queue up two tasks
spawn(function()
    print("Task 1")
end)
spawn(function()
    print("Task 2")
end)
 
-- Wait, which allows the other tasks to be resumed
print("Main task waiting")
wait()
 
print("Main task end")
Main task
Main task waiting
Task 1
Task 2
Main task end

Additionally, new tasks can be run when a queued task terminates - with no wait() in the above code:

print("Main task")
 
-- Queue up two tasks
spawn(function()
    print("Task 1")
end)
spawn(function()
    print("Task 2")
end)
 
print("Main task end")
Main task
Main task end
Task 1
Task 2

ypcall[edit]

ypcall queues a task, and then pauses the current task until either the queued task completes or errors

Implementation details[edit]

The following code shows a roblox thread scheduler written in lua that (seems to) behave in the same way as the builtin one:

function wait(time)
    enqueue_task{coro=coroutine.wrap(fn), at=tick() + time}
    return coroutine.yield()
end
 
function spawn(fn)
    enqueue_task{coro=coroutine.wrap(fn), at=tick()}
end
 
function delay(time, fn)
    enqueue_task{coro=coroutine.wrap(fn), at=tick() + time}
end
 
local tasks = {}
function enqueue_task(t)
    -- there are more efficient ways to insert and sort, but oh well...
    tasks[#tasks + 1] = t
    table.sort(tasks, function(a, b) return a.at < b.at end)
end
 
-- The main scheduler
while true do
    local now = tick()
    if #tasks ~= 0 and tasks[1].at <= now then
        local t = table.remove(tasks, 1)
        coroutine.resume(t.coro, now - t.at, now)
    end
end

This does not cover:

  • bare coroutine.yield() behaving like wait
  • pcall

See also[edit]

  • Coroutines - internally, these are used by the thread scheduler