local n={}n.__index=n function n.new()return setmetatable({_handlerListHead=false},n)end function n.Connect(T,n)local Y=Connection.new(T,n)Y._next=T._handlerListHead and T._handlerListHead or Y._next T._handlerListHead=Y return Y end function n.Fire(n,...)local T=n._handlerListHead while T do if T._connected then if not freeRunnerThread then freeRunnerThread=coroutine.create(function(...)acquireRunnerThreadAndCallEventHandler(...)while true do acquireRunnerThreadAndCallEventHandler(coroutine.yield())end end)end task.spawn(freeRunnerThread,T._fn,...)end T=T._next end end function n.Wait(n)local T=coroutine.running()local Y Y=n:Connect(function(...)Y:Disconnect()task.spawn(T,...)end)return coroutine.yield()end return n


local Signal = {}
Signal.__index = Signal

function Signal.new()
	return setmetatable({_handlerListHead = false}, Signal)
end

function Signal:Connect(fn)
	local connection = Connection.new(self, fn)
	connection._next = (self._handlerListHead and self._handlerListHead) or connection._next
	self._handlerListHead = connection
	return connection
end

function Signal:Fire(...)
	local item = self._handlerListHead
	while item do
		if item._connected then
			if not freeRunnerThread then
				freeRunnerThread = coroutine.create(function(...)
					acquireRunnerThreadAndCallEventHandler(...)
					while true do
						acquireRunnerThreadAndCallEventHandler(coroutine.yield())
					end
				end)
			end
			task.spawn(freeRunnerThread, item._fn, ...)
		end
		item = item._next
	end
end

function Signal:Wait()
	local waitingcoroutine = coroutine.running()
	local connect;
	connect = self:Connect(function(...)
		connect:Disconnect()
		task.spawn(waitingcoroutine, ...)
	end)
	return coroutine.yield()
end

return Signal
