function TaskScheduler.CreateScheduler(T,F)local r={}local u={}local V=true local J local n=nil local D=tick()runService.RenderStepped:Wait()local function m()lastIteration=tick()for F=#frameUpdateTable,1,-1 do frameUpdateTable[F+1]=frameUpdateTable[F]>=lastIteration-1 and frameUpdateTable[F]or nil end frameUpdateTable[1]=lastIteration end local function N()n=runService.RenderStepped:Connect(m)while true do if V then break end local T=tick()-D>=1 and#frameUpdateTable or#frameUpdateTable/(tick()-D)if T>=F and tick()-frameUpdateTable[1]<1/F then if#u>0 then u[1]()table.remove(u,1)else V=true break end else runService.RenderStepped:Wait()end end n:Disconnect()n=nil end function r.Pause(F)J=true V=true end function r.Resume(F)if J then J=false V=false N()end end function r.Destroy(F)r:Pause()for F in pairs(r)do r[F]=nil end setmetatable(r,{__index=function()error("\065\116\116\101\109\112\116 \116\111 \117\115\101 \100\101\115\116\114\111\121\101\100 \115\099\104\101\100\117\108\101\114")end,__newindex=function()error("\065\116\116\101\109\112\116 \116\111 \117\115\101 \100\101\115\116\114\111\121\101\100 \115\099\104\101\100\117\108\101\114")end})end function r.QueueTask(F,T)u[#u+1]=T if V and not J then V=false N()end end return r end return TaskScheduler
--[[
	param targetFps  Task scheduler won't run a task if it'd make the FPS drop below this amount
					 (WARNING) this only holds true if it is used properly. If you try to complete 10 union operations
					 at once in a single task then of course your FPS is going to drop -- queue the union operations
					 up one at a time so the task scheduler can do its job.
					
					
	returns scheduler
		method Pause      Pauses the scheduler so it won't run tasks. Tasks may still be added while the scheduler is
						  paused. They just won't be touched until it's resumed. Performance efficient -- disables
						  execution loop entirely until scheduler is resumed.
		
		method Resume     Resumes the paused scheduler.
		
		method Destroy    Destroys the scheduler so it can't be used anymore.
		
		method QueueTask  Queues a task for automatic execution.
			param callback  function (task) to be run.
	
	Example usage:
	
	local scheduler = TaskScheduler:CreateScheduler(60)
	local totalOperations = 0
	local paused
	for i=1,100 do
		scheduler:QueueTask(function()
			local partA = Instance.new("Part", workspace)
			local partB = Instance.new("Part", workspace)
			plugin:Union({partA, partB}):Destroy()
			totalOperations = totalOperations + 1
			print("Times unioned:", totalOperations)
			if (totalOperations == 50) then
				scheduler:Pause()
				paused = true
			end
		end)
	end
	
	repeat wait() until paused
	wait(2)
	scheduler:Resume()
--]]

function TaskScheduler:CreateScheduler(targetFps)
	local scheduler = {}
	local queue = {}
	local sleeping = true
	local paused

	local updateFrameTableEvent = nil

	local start = tick()
	runService.RenderStepped:Wait()

	local function UpdateFrameTable()
		lastIteration = tick()
		for i = #frameUpdateTable, 1, -1 do
			frameUpdateTable[i + 1] = ((frameUpdateTable[i] >= (lastIteration - 1)) and frameUpdateTable[i] or nil)
		end
		frameUpdateTable[1] = lastIteration
	end

	local function Loop()
		updateFrameTableEvent = runService.RenderStepped:Connect(UpdateFrameTable)
		while true do
			if sleeping then
				break
			end
			local fps = (((tick() - start) >= 1 and #frameUpdateTable) or (#frameUpdateTable / (tick() - start)))
			if fps >= targetFps and (tick() - frameUpdateTable[1]) < (1 / targetFps) then
				if #queue > 0 then
					queue[1]()
					table.remove(queue, 1)
				else
					sleeping = true
					break
				end
			else
				runService.RenderStepped:Wait()
			end
		end
		updateFrameTableEvent:Disconnect()
		updateFrameTableEvent = nil
	end

	function scheduler.Pause(_s)
		paused = true
		sleeping = true
	end

	function scheduler.Resume(_s)
		if paused then
			paused = false
			sleeping = false
			Loop()
		end
	end

	function scheduler.Destroy(_s)
		scheduler:Pause()
		for i in pairs(scheduler) do
			scheduler[i] = nil
		end
		setmetatable(scheduler, {
			__index = function()
				error("Attempt to use destroyed scheduler")
			end,
			__newindex = function()
				error("Attempt to use destroyed scheduler")
			end,
		})
	end

	function scheduler.QueueTask(_s, callback)
		queue[#queue + 1] = callback
		if sleeping and not paused then
			sleeping = false
			Loop()
		end
	end

	return scheduler
end

return TaskScheduler
