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.
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)
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!")
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
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