Skip to content

Latest commit

 

History

History
139 lines (106 loc) · 2.97 KB

9-task-scheduler.mdx

File metadata and controls

139 lines (106 loc) · 2.97 KB

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