Skip to content
IS4 edited this page Jun 19, 2021 · 2 revisions

Scheduling functions

The timer package contains the necessary functions to synchronize the execution of Lua code based on time events. Functions ms and tick allow the caller to schedule the execution of a specific function based on a time interval, specified either in milliseconds, or using server ticks.

timer.ms(function()
  print("Hello") -- printed after 1 second
end, 1000)

The first argument to both these functions is a function that should be executed; the second is an integer specifying the time interval. YALP stores the function and the rest of the arguments into a queue based on the interval and executes it when the time is reached. The time interval can be also negative or 0, in which case the execution will happen as soon as possible.

The async function pattern can be used to write simpler asynchronous code. It expects the callee to yield a registration function, which will be provided with a continuation function that resumes the coroutine. In this case, yielding either of the two functions in timer works, in the following way:

async(function()
  print("start")
  coroutine.yield(timer.ms, 1000)
  print("after 1 s");
  coroutine.yield(timer.tick, 100)
  print("after 100 ticks")
end)

Parallel execution

Lua is single-threaded and its coroutines can only be used to achieve cooperative multitasking. However, it has a system which allows to pause the execution of any code after any amount of time. It is possible to specify a hook to be called after a specific number of Lua instructions, and the hook is allowed to yield, pausing the running coroutine.

This is performed by timer.parallel. This function takes another function and runs it, setting a hook that yields every 100000 instructions (you can specify another count as the first argument, moving the function one to the second place). If run in the async function, the code will yield after the specific number of instructions, and timer.tick will be called to execute the rest of the function on the next server tick. The hook will only affect the current coroutine and not other code, and will be automatically removed when the function ends.

async(function()
  timer.parallel(function()
    for i = 1, 500000 do
      if (i % 100000) == 0 then
        print(i)
      end
    end
  end)
end)

Decreasing the count value will slow down the execution of Lua code, but if it takes a long time to perform it (due to the complexity of the code itself), this is a safe option. However, this should not be used to execute a native function that lags the server, because it will actually not run it in a separate thread and will not affect the performance of the server. This can be only used for Lua code.

There is also another function, timer.parallelreg, which allows you to specify the registration function that is yielded to async. In the previous function, it was implicitly function(cont)timer.tick(cont, 1)end, but it you want to provide a different function that handles the continuation (as if you yielded it yourself), you can specify it as the second argument after the executed function to timer.parallelreg.