[fixed] Working coroutines

Unfortunately, coroutines are currently broken

To get around this, I made a lua module that basically emulates coroutines using BindableEvents
It has an identical API to lua coroutines so it is very easy to swap in by adding to the top of your script local coroutine=require(path.to.coroutine)

The only downsides are that it:

  • can’t get function return values if thread isn’t made with the module
  • can’t resume threads that aren’t yielded with the module (e.g: wait,BindableEvents,actual coroutines,etc)

The first one is rarely used though (and when you do need it simply just wrap the Roblox thread in a coroutine made by this module) and the second is only used if you have some ultra hacky code(? if you have use cases for it I’m very curious to see ;P) so these two restrictions are more or less negligible

Here is a Roblox model of the code

If you find any bugs/have suggestions please message me on discord Acreol#0001

Thanks

--[[
	
	Fix to https://devforum.roblox.com/t/modulescripts-that-yield-with-coroutine-yield-will-break-parent-thread/239567
	
	Can't get function return Values if thread isn't made with this module
	Can't resume threads that aren't yielded with this module (e.g: wait,BindableEvents,actual coroutines,etc)
	
	
--]]

local md={}
local data=setmetatable({},{
	__mode='k',
	__index=function(data,t)
		data[t]={
			ev=Instance.new('BindableEvent'),
			args={},--passed through resume
			ret={},--returned from function/yield
		}
		return data[t]
	end,
})

local function pack(...)
	return{n=select('#',...),...,}
end
md.running=coroutine.running
md.status=coroutine.status
md.yield=function(...)
	local data=data[md.running()]
	data.ret=pack(...)
	data.ev.event:Wait()
	return unpack(data.args,1,data.args.n)
end
md.resume=function(t,...)
	local data=data[t]
	data.args=pack(...)
	data.ret={}
	local ok,msg=pcall(data.ev.fire,data.ev)
	data.args={}
	local ret=data.ret
	data.ret={}
	if ok then
		return ok,unpack(ret,1,ret.n)
	else
		return ok,msg
	end
end
md.create=function(f)
	local t
	coroutine.wrap(function()
		t=md.running()
		data[t].ret=pack(f(md.yield()))
	end)()
	return t
end
md.wrap=function(f)
	return coroutine.wrap(function(...)
		data[md.running()].ret=pack(f(...))
	end)
end
return md
7 Likes

Just so you know hastebin does wipe their pages every so often and so the code you linked is unavailable for me at present (Atleast on mobile anyway) - if it is available for other users it might not be in the near future.

2 Likes