Will this have any performance benefits over coroutines and spawn?
Do libraries run on C++? I thought they went through Lua.
You shouldn’t be doing this anyways, it’s no wonder it would crash.
I’m not 100% sure, since this is directly using the task manager, I’m assuming the task manager is run on C++.
The fact that there is a crash is a problem regardless of whether or not its good practice to be spawning a bunch of threads.
It turns out the reason is unrelated to the task.spawn
calls, a few other people, Hal and I have been discussing and it turns out that task.spawn
crashes after a certain number of arguments, and the last few arguments start becoming nil:
task.spawn(print, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48)
Crashes 100% of the time on my machine.
task.spawn(print, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47)
Crashes 0% of the time on my machine, followed by 3 nil
values:
The amount of arguments that can be used before a crash seems to differ per machine but weirdly its remained consistent in every test I’ve done, and seems to be consistent for others.
It solves that issue: task.wait(delay)
will dutifully unsuspend after the delay regardless of what the performance consequences may be, compared to wait(delay)
which “helpfully” throttled execution for you, sometimes delaying resumption by extra frames in an attempt to keep the frame rate smooth.
I can confirm that 44 arguments is currently 100% safe, any more must be avoided for now.
So, as long as you aren’t passing arbitrarily long variable argument lists to the API you won’t run into this issue (unless you actually wrote code that takes more than 44 hand-coded arguments… I won’t judge).
Is it safe to use task.desynchronize and task.synchronize now? Cuz this wasn’t mentioned in this thread.
I have the same question. I’d like to make my code as efficient as possible. I know that coroutine isn’t true multitasking, so I’d assume that this new library is effectively just coroutines, but with true multitasking, and can hence be interchangeable. But someone please correct me if I am wrong.
Wow. This is amazing. defer
and delay
will probably be my most used.
This release changes nothing about the status of parallel Lua. This release is only about the functions mentioned in the main post.
This is one of the greatest updates, I’m already starting to use it and I like how simple it is! I’m also looking forward to updates concerning this new library, such as the possibility to cancel!
Gosh dang it, not more deprecations.
Not saying this is a bad update at all but I already got 6000+ deprecrations and now there’s gonna be more, erugh!
Yes, those methods are meant to be replaced by these.
Don’t worry, for something pervasive like this we’ll give plenty of time for your code to naturally shift over to the new API before bothering you with squiggly lines.
Love all the features added with this update
one small issue I think was missed but when trying to use task.spawn on the running coroutine it crashes
^^ this occurs every time
Why not just write a library to do this? I can’t imagine it’s that difficult to make an object that mirrors this behavior.
Maybe
debounce.fromRBXSignal or debounce.new
I think that would be pretty redundant, using debounce by scheduling something to happen later on is already a redundancy, it can be done in a way that is more modern, like comparing the current time in real-time to when it was last executed, that’s far less extraneous in complexity (saves idle polling, and the purpose of the if
is clearer.), and makes it quite a bit more accurate.
E.g:
local lastTouch = os.clock()
local debounceTime = 3
local function PartTouched()
if os.clock() > lastTouch then
print("The part")
lastTouch = os.clock() + debounceTime
end
end
Glad someone mentioned this, I second this completely. Take a look at this hypothetical scenario:
local module = {}
local active = false
local function IncrementStamina()
if active then
task.delay(0.5, IncrementStamina)
-- increment stamina here
end
end
function Module.Start()
active = true
task.delay(0.5, IncrementStamina)
end
function Module.Stop()
active = false
end
return Module
The problem with this code is that whenever Stop
is called, the task.delay
internally will still continue scheduling the ‘IncrementStamina’ function for however much time it had remaining, resulting in some idle polling and also makes the function a bit uglier by requiring an if
statement to determine if it should still be running. if the Stop
function could just be this:
function Module.Stop()
task.undelay(IncrementStamina)
end
None of those issues would then be present.
However, on the other side of the coin; adding an undelay
or similar function with the purpose of cancelling a currently active ‘delayed’ function would require a change to how they store your functions in the queue internally, if that queue weren’t already classed through function memory addresses, it would then have to be for that to work, or anything similar. So I have my doubts that such a function will ever be added, but maybe they’ll find a way.