Task Library - Now Available!

Is it safe to use task.desynchronize and task.synchronize now? Cuz this wasn’t mentioned in this thread.

1 Like

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.

2 Likes

Wow. This is amazing. defer and delay will probably be my most used.

1 Like

This release changes nothing about the status of parallel Lua. This release is only about the functions mentioned in the main post.

6 Likes

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!

1 Like

Gosh dang it, not more deprecations. :triumph:
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.

13 Likes

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

3 Likes

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

1 Like

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
2 Likes

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. :man_shrugging:

2 Likes

I actually know how to do that. but adding such functions would make it easier for someone who just started to code in the platform

Is there any benefit to using task.spawn() over coroutine.wrap()()? (Besides length)

1 Like

to my knowledge, coroutine.wrap propogates the stack trace of the function to you, which means it isn’t perfect and doesn’t always appear correctly. task.spawn on the other hand I believe gives you the native stack trace, task.spawn also does not suspend the execution of the thread that called spawn whenever an error occurs, whereas coroutine.wrap will, overall I think it would be better to use task.spawn for it’s nice-to-haves.

3 Likes

I think theres somewhat of a misunderstanding here in regards to the coroutine library vs this new library.

Coroutines essentially run instantly, allowing for stuff to run immediately, however that does create a problem in regards to efficiency. Having tons of stuff running immediately will cause serious lag spikes, whereas task.spawn() would still defer to the next step of the task scheduler, which in theory, should smooth out the lag spikes.

This is why people still preferred using spawn() this entire time over coroutines, because as long as they were sensible with their usage, it added some modest performance gain, should that be a necessity. You could treat coroutines similarly, but eventually scale does become a problem and a mild delay vs occasional lag spikes seems like a far better trade off than anything else to me.

6 Likes

Tyvm this will be very useful API for future projects! :heart:

This debounce would be pretty useless for games anyway. For example if you were making a lazer you wouldn’t want this debounce (as if someone touched the lazer now you would have to wait 3 seconds for the cooldown), you would want an individual debounce for each player.

2 Likes

For the short time at least that I tested, task.spawn runs more quickly than using coroutine.wrap at least, I don’t think that’s the case, or at least not the reason;

I do recommend using task.defer for anything you don’t need to run instantly, but yeah I don’t know exactly how the scheduler and everything works, for optimization I just go for rule of thumb stuff, I could be wrong here;

1 Like

Oh man, the linter really doesn’t like some of these methods.

1 Like