Concur
Concurrency class for helping run tasks concurrently. In other words, Concur allows developers to watch coroutines/threads. Completion status, returned values, and errors can all be tracked.
For instance, Concur could be used to concurrently save all player data at the same time when the game closes down:
game:BindToClose(function()
local all = {}
for _,player in Players:GetPlayers() do
local save = Concur.spawn(function()
DoSomethingToSaveData(player)
end)
table.insert(all, save)
end
local allConcur = Concur.all(all)
allConcur:Await()
end)
Types
Errors
interface
Errors {
Stopped:
"Stopped"
Timeout:
"Timeout"
}
Properties
Errors
This item is read only and cannot be modified. Read OnlyConcur.Errors:
Errors
Functions
spawn
Spawns the function using task.spawn
.
local c = Concur.spawn(function()
task.wait(5)
return "Hello!"
end)
c:OnCompleted(function(err, msg)
if err then
error(err)
end
print(msg) --> Hello!
end))
defer
Same as Concur.spawn
, but uses task.defer
internally.
delay
Same as Concur.spawn
, but uses task.delay
internally.
value
Resolves to the given value right away.
local val = Concur.value(10)
val:OnCompleted(function(v)
print(v) --> 10
end)
event
Completes the Concur instance once the event is fired and the predicate
function returns true
(if no predicate is given, then completes once
the event first fires).
The Concur instance will return the values given by the event.
-- Wait for next player to touch an object:
local touch = Concur.event(part.Touched, function(toucher)
return Players:GetPlayerFromCharacter(toucher.Parent) ~= nil
end)
touch:OnCompleted(function(err, toucher)
print(toucher)
end)
all
Completes once all Concur instances have been completed. All values will be available in a packed table in the same order they were passed.
local c1 = Concur.spawn(function()
return 10
end)
local c2 = Concur.delay(0.5, function()
return 15
end)
local c3 = Concur.value(20)
local c4 = Concur.spawn(function()
error("failed")
end)
Concur.all({c1, c2, c3}):OnCompleted(function(err, values)
print(values) --> {{nil, 10}, {nil, 15}, {nil, 20}, {"failed", nil}}
end)
first
Completes once the first Concur instance is completed without an error. All other Concur instances are then stopped.
local c1 = Concur.delay(1, function()
return 10
end)
local c2 = Concur.delay(0.5, function()
return 5
end)
Concur.first({c1, c2}):OnCompleted(function(err, num)
print(num) --> 5
end)
Stop
Concur:
Stop
(
) →
(
)
Stops the Concur instance. The underlying thread will be cancelled using
task.cancel
. Any bound OnCompleted
functions or threads waiting with
Await
will be completed with the error Concur.Errors.Stopped
.
local c = Concur.spawn(function()
for i = 1,10 do
print(i)
task.wait(1)
end
end)
task.wait(2.5)
c:Stop() -- At this point, will have only printed 1 and 2
IsCompleted
Concur:
IsCompleted
(
) →
boolean
Check if the Concur instance is finished.
Await
This is a yielding function. When called, it will pause the Lua thread that called the function until a result is ready to be returned, without interrupting other scripts. YieldsConcur:
Await
(
timeout:
number?
) →
(
Error
,
...any?
)
Yields the calling thread until the Concur instance is completed:
local c = Concur.delay(5, function()
return "Hi"
end)
local err, msg = c:Await()
print(msg) --> Hi
The Await
method can be called after the Concur instance
has been completed too, in which case the completed values
will be returned immediately without yielding the thread:
local c = Concur.spawn(function()
return 10
end)
task.wait(5)
-- Called after 'c' has been completed, but still captures the value:
local err, num = c:Await()
print(num) --> 10
It is always good practice to make sure that the err
value is handled
by checking if it is not nil:
local c = Concur.spawn(function()
error("failed")
end)
local err, value = c:Await()
if err ~= nil then
print(err) --> failed
-- Handle error `err`
else
-- Handle `value`
end
This will stop awaiting if the Concur instance was stopped
too, in which case the err
will be equal to
Concur.Errors.Stopped
:
local c = Concur.delay(10, function() end)
c:Stop()
local err = c:Await()
if err == Concur.Errors.Stopped then
print("Was stopped")
end
An optional timeout can be given, which will return the
Concur.Errors.Timeout
error if timed out. Timing out
does not stop the Concur instance, so other callers
to Await
or OnCompleted
can still grab the resulting
values.
local c = Concur.delay(10, function() end)
local err = c:Await(1)
if err == Concur.Errors.Timeout then
-- Handle timeout
end
OnCompleted
Concur:
OnCompleted
(
fn:
(
Error
,
...any?
)
→
(
)
,
timeout:
number?
) →
(
)
→
(
)
Calls the given function once the Concur instance is completed:
local c = Concur.delay(5, function()
return "Hi"
end)
c:OnCompleted(function(err, msg)
print(msg) --> Hi
end)
A function is returned that can be used to unbind the function to no longer fire when the Concur instance is completed:
local c = Concur.delay(5, function() end)
local unbind = c:OnCompleted(function()
print("Completed")
end)
unbind()
-- Never prints "Completed"
The OnCompleted
method can be called after the Concur instance
has been completed too, in which case the given function will be
called immediately with the completed values:
local c = Concur.spawn(function()
return 10
end)
task.wait(5)
-- Called after 'c' has been completed, but still captures the value:
c:OnCompleted(function(err, num)
print(num) --> 10
end)
It is always good practice to make sure that the err
value is handled
by checking if it is not nil:
local c = Concur.spawn(function()
error("failed")
end)
c:OnCompleted(function(err, value)
if err ~= nil then
print(err) --> failed
-- Handle error `err`
return
end
-- Handle `value`
end)
This will call the function if the Concur instance was stopped
too, in which case the err
will be equal to
Concur.Errors.Stopped
:
local c = Concur.delay(10, function() end)
c:OnCompleted(function(err)
if err == Concur.Errors.Stopped then
print("Was stopped")
end
end)
c:Stop()
An optional timeout can also be supplied, which will call the
function with the Concur.Errors.Timeout
error:
local c = Concur.delay(10, function() end)
c:OnCompleted(function(err)
if err == Concur.Errors.Timeout then
-- Handle timeout
end
end, 1)