SharpForge maps async/await to Lua coroutines. Only Task from SFLib.Async is supported; System.Threading.Tasks.Task is not.
An async Task method lowers to a function that returns SF__.CorRun__(function() ... end). The coroutine body wraps the method body.
using SFLib.Async;
public static class Waves
{
public static async Task Spawn()
{
await Task.Delay(1000);
SpawnUnit();
}
}function SF__.Waves.Spawn()
return SF__.CorRun__(function()
SF__.CorWait__(1000)
SpawnUnit()
end)
endawait Task.Delay(ms) lowers to SF__.CorWait__(ms). This suspends the coroutine using a WC3 timer and resumes it after ms milliseconds.
The timer pool helpers are emitted automatically when Task.Delay is used:
function SF__.CorRun__(fn)
local thread = coroutine.create(fn)
local ok, err = coroutine.resume(thread)
if not ok then error(err) end
return thread
end
function SF__.CorWait__(milliseconds)
if milliseconds <= 0 then return end
local thread = coroutine.running()
local timer = SF__.CorAcquireTimer__()
TimerStart(timer, milliseconds / 1000, false, function()
local ok, err = coroutine.resume(thread)
SF__.CorReleaseTimer__(timer)
if not ok then error(err) end
end)
return coroutine.yield()
end
function SF__.CorAcquireTimer__()
local size = SF__.CorTimerPoolSize__
if size > 0 then
local timer = SF__.CorTimerPool__[size]
SF__.CorTimerPool__[size] = nil
SF__.CorTimerPoolSize__ = size - 1
return timer
end
return CreateTimer()
end
function SF__.CorReleaseTimer__(timer)
PauseTimer(timer)
local size = SF__.CorTimerPoolSize__
if size < SF__.CorMaxTimerPoolSize__ then
size = size + 1
SF__.CorTimerPool__[size] = timer
SF__.CorTimerPoolSize__ = size
else
DestroyTimer(timer)
end
endSimple yield return sequences in a method are materialized into a List<T> at call time. The method returns a List<T> containing all yielded values.
Task<T> (a task with a return value), async methods without await, CancellationToken, and ValueTask produce a transpiler error.