Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local function Tuple(...)
- local r,n = {...},select("#",...)
- return function()
- return unpack(r,1,n)
- end
- end
- local Scheduler = {
- Threads = {
- Running = {};
- Waiting = {};
- }; Fire = {};
- Events = {};
- }
- local Task do
- local function start(...) Scheduler:Start(...) end
- local function stop(...) Scheduler:Stop(...) end
- local taskMeta = {__tostring = function(s) return s.name end,__index=function(s,k)
- if k:lower() == "start" then return start end
- if k:lower() == "stop" then return stop end return rawget(s,k:lower())
- end}
- function Task(name,func,...)
- local task = setmetatable({
- name = name; c = false;
- status="new",args=Tuple(...),
- thread = coroutine.create(func)
- },taskMeta)
- local function w(t)
- local start,y = tick()
- Scheduler.Threads.Waiting[task] = true
- task.status = "waiting"
- repeat local c = coroutine.yield()
- y = tick()-start
- until not c and (t or 0) < y
- task.status = "running"
- Scheduler.Threads.Waiting[task] = nil
- return t,elapsedTime()
- end
- setfenv(func,setmetatable({wait=w,Wait=w},{__index=getfenv(func)}))
- return task
- end
- end
- function Scheduler:AddEvent(ev)
- local be = Instance.new("BindableEvent")
- self.Events[ev] = be.Event
- self.Fire[ev] = function(...) be:Fire(...) end
- end
- function Scheduler:FireEvent(ev,...)
- self.Fire[ev](...)
- end
- function Scheduler:Start(task,...)
- if Scheduler.Threads.Running[task] then return end
- Scheduler.Threads.Running[task] = Tuple(...)
- Scheduler:FireEvent("Started",task)
- end
- function Scheduler:Stop(task)
- Scheduler.Threads.Running[task] = nil
- Scheduler:FireEvent("Stopped",task,false)
- end
- Scheduler:AddEvent("Started") -- Started(task) (Fired whenever someone starts a task)
- Scheduler:AddEvent("Stopped") -- Stopped(task,ended) (Fired when stopped, or ended == true when end of thread)
- --NOTE: If you start an already ended thread, it'll fire Stopped(task,true) the next tick (because it's dead)
- Scheduler:AddEvent("Ran") -- Ran(task,...) (Task runs for first time, also returns the passed args)
- local REPORTED = false
- spawn(function()
- while true do
- for k,v in pairs(Scheduler.Threads.Running) do
- if coroutine.status(k.thread) == "dead" then
- Scheduler:FireEvent("Stopped",k,true)
- Scheduler.Running[k] = nil
- elseif k.status == "running" then
- if not k.c then k.c = true
- print(tick(),"~Thread",k,"is yielding C-sided")
- end
- else
- if k.status == "new" then
- k.status = "running"
- coroutine.resume(k.thread,v())
- else
- coroutine.resume(k.thread)
- end k.c = false
- end
- end wait(0)
- end
- end)
- local task = Task("Test",function(...) print("args:",...) while wait(1) do print("hi") end end)
- -- Properties: Name,Status (also Args,C and Thread, but those should only be used internally)
- -- ... being extra arguments
- Scheduler:Start(task,"lol",nil)
- --OR (Starting a task multiple times has no effect)
- task:Start(...)
- wait(2)
- Scheduler:Stop(task)
- --OR (Stopping a task multiple times has no effect)
- task:Stop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement