Reusing threads

Is it possible to make a module that does not use Roblox Bindable Events that reuses threads?
Basically what I mean is:

you have a function that calls a set of other functions {a,b,c,…} and passes some parameters

for i = 1,#s do
s[i]()
end

so that makes all the functions use the current thread and thus reusing is achieved
but I also want to make it so when one function yields, a new thread is created for it to run on and the rest of the functions can continue being called on the original thread

btw I want this process to be automatic so that means no manually wrapping the functions if I know they will yield

1 Like

What are you trying to do exactly? Why not just create a new thread for each function call.

2 Likes

reusing threads would be more efficient though and this is more to learn than for anything in particular

http://wiki.c2.com/?PrematureOptimization

3 Likes

I think that’s silly. Unless you’re doing something insane you would not need to use the same threads for that.

I think you could do something like this using coroutines but it may not be actually faster. How I would do this is I would have one current coroutine that runs each function and use coroutine.status to check if it has yielded yet (ready for the next function call). If it is not ready, I would create a new coroutine to run the next function.

e.g

function runFunctionLoop()
  while true do
    local f, args = coroutine.yield()
    if f == nil then break end
    f(unpack(args))
    if typeof(f) == "function" then
      f(unpack(args))
    end
  end
end

-- Resumes a coroutine one last time to stop the loop running
function disposeCoroutine(coro)
  spawn(function()
    coroutine.resume(coro)
  end)
end

local myFunctionRunner = coroutine.create(runFunctionLoop)
coroutine.resume(myFunctionRunner)

for i = 1,#s do
  if coroutine.status(myFunctionRunner) == "running" then
    -- Last function yielded? Create a new thread to run the next function.
    disposeCoroutine(myFunctionRunner)
    myFunctionRunner = coroutine.create(runFunctionLoop)
    coroutine.resume(myFunctionRunner)
  end
  coroutine.resume(myFunctionRunner, s[i], {})
end

I have not tested this code, but you can probably get a basic idea of how it can be done. It is likely even slower than just using a new thread for each function though, so it might be interesting to benchmark it.

3 Likes

So when running code that has no yielding in it, you are guaranteed it will all run in one block and the pseudo lua thread scheduler won’t pause the code to run other code in between?

Yeah, I think so. The two main potential problems I see with the code I posted is if coroutine.resume will resume the coroutine after the current thread has finished running (in which case it will always create a new coroutine) or if there is a problem with how wait interacts with coroutine.yeild (see here).

1 Like