According to my knowledge on coroutines
- which may be wrong -, threads created by coroutine.wrap
are executed somewhere else, not yielding the current thread.
However, when I run a coroutine
that delays itself, it still is yielding the current thread.
Am I doing something wrong? Is that how it's supposed to work?
My code is below:
local CustomDelay = coroutine.wrap(function(tim,f) tim = tonumber(tim) if type(f)~='function' then f = function() end end if not tim then tim=0 end local supposedtime = os.time()+tim local function uselessfunction() -- Do nothing end print('Delaying function "' .. (function() local str = tostring(f); if not str then str = 'function: UnknownHexAddress' end str=str:sub(10) return str end)() .. '" (' .. tostring(tim) .. ') seconds.') repeat uselessfunction() until os.time()>=supposedtime -- Alternative to wait() local s,e = pcall(f) if not s then warn('Error while delaying function: ' .. e) end return s,e end) CustomDelay(3,function() print"Woo!" end)) -- Delays the function 3 seconds, supposedly not affecting the current thread warn("This should come before the 'Woo!', since it is not delayed")
PS.: I know I wouldn't be able to use coroutine.wrap
like that, since if I ran CustomDelay again it'd error that CustomDelay was dead - I was just using it for the example.
Lua is not multithreaded -- all coroutines run on the same thread. Thus busy-waiting loops like you've written block everything until it's done.
A coroutine describes the place it's executing at (and all the local variables). resume
and yield
switches between which coroutine is being actively used by the interpreter. But this is a switch -- only one can be active at a time.
Due to careful scheduling, it looks like many coroutines are happening at the same time. What is actually happening is that things like wait
make the current coroutine yield; after the current ROBLOX-managed-coroutine yields, ROBLOX looks for the next coroutine that needs to be started (e.g., because an event fired, or because the duration of a wait
ended), and resumes that one.
I highly recommend not putting more than one statement on a line, and putting spaces around operators (e.g., +
or =
).
You can do some code cleanup in your script.
if not tim then tim=0 end
can be replaced with tim = tim or 0
.tim = tonumber(tim) or 0
, though I'm not really sure why you want to accept non-numbers as the first parameter.f
to a function if it's not.str
. Except that tostring
can't return nil
, so that shouldn't happen.At this point you have something like this:
local function doNothing() -- Do nothing end local CustomDelay = coroutine.wrap(function(tim,f) tim = tonumber(tim) or 0 assert(type(f) == "function") local supposedtime = os.time() + tim local function functionHex() return tostring(f):sub(10) end print('Delaying function "' .. functionHex() .. '" (' .. tostring(tim) .. ') seconds.') repeat doNothing() until os.time() >= supposedtime -- Alternative to wait() local s,e = pcall(f) if not s then warn('Error while delaying function: ' .. e) end return s,e end) CustomDelay(3,function() print("Woo!") end) -- Delays the function 3 seconds, supposedly not affecting the current thread warn("This should come before the 'Woo!', since it is not delayed")
functionHex
really doesn't need to pull the local f
out. You should just make it an argument and move it outside of CustomDelay
.The result is much cleaner:
local function doNothing() -- Do nothing end local function functionHex(f) return tostring(f):sub(10) end local CustomDelay = coroutine.wrap(function(tim,f) tim = tonumber(tim) or 0 assert(type(f) == "function") local supposedtime = os.time() + tim print('Delaying function "' .. functionHex(f) .. '" (' .. tostring(tim) .. ') seconds.') repeat doNothing() until os.time() >= supposedtime -- Alternative to wait() local s, e = pcall(f) if not s then warn('Error while delaying function: ' .. e) end return s, e end) CustomDelay(3,function() print("Woo!") end) -- Delays the function 3 seconds, supposedly not affecting the current thread warn("This should come before the 'Woo!', since it is not delayed")