The Task Scheduler
Lune has a built-in task scheduler, which can let you run things at fixed intervals, ensure some work happens after everything else is already done, and more.
Spawning Tasks & Waiting
This example script will run several tasks concurrently, in lightweight Lua threads, also known as coroutines:
local task = require("@lune/task")
print("Hello, scheduler!")
task.spawn(function()
print("Spawned a task that will run instantly but not block")
task.wait(2)
print("The instant task resumed again after 2 seconds")
end)
print("Spawning a delayed task that will run after 5 seconds")
task.delay(5, function()
print("Waking up from my deep slumber...")
task.wait(1)
print("Hello again!")
task.wait(1)
print("Goodbye again! 🌙")
end)
Deferring Work
This example script runs a bit of work after all other threads have finished their work or are yielding waiting for some other result:
local task = require("@lune/task")
task.defer(function()
print("All the scheduled work has finished, let's do some more!")
local a = 0
for _ = 1, 100000 do
local b = a + 1
end
print("Phew, that was tough.")
end)
print("Working...")
local s = ""
for _ = 1, 5000 do
s ..= ""
end
print("Done!")
Advanced Usage & Async
Spawning tasks like this can be very useful together with asynchronous APIs from other built-in
libraries, such as net.request
:
local net = require("@lune/net")
local task = require("@lune/task")
local completed = false
task.spawn(function()
while not completed do
print("Waiting for response...")
task.wait() -- Wait the minimum amount possible
end
print("No longer waiting!")
end)
print("Sending request")
net.request("https://google.com")
print("Got response")
completed = true
Bonus
Barebones Signal Implementation
Using the task library, it becomes trivial to implement signal objects that take callbacks to run when a signal is fired, and that can handle both synchronous and yielding (async) callbacks without additional complexity:
local task = require("@lune/task")
local function newSignal()
local callbacks = {}
local function connect(callback: (...any) -> ())
table.insert(callbacks, callback)
end
local function fire(...: any)
for _, callback in callbacks do
task.spawn(callback, ...)
end
end
return connect, fire
end
local connectToThing, fireThing = newSignal()
connectToThing(function(value)
print("Callback #1 got value:", value)
task.wait(1)
print("Callback #1 still has value:", value)
end)
connectToThing(function(value)
print("Callback #2 got value:", value)
task.wait(0.5)
print("Callback #2 still has value:", value)
end)
print("Before firing")
fireThing(123)
print("After firing")
--> Before firing
--> Callback #1 got value: 123
--> Callback #2 got value: 123
--> After firing
--> ...
--> Callback #2 still has value: 123
--> ...
--> Callback #1 still has value: 123