Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local Task
- do
- local time = os.time
- local unpack = table.unpack
- local status = coroutine.status
- local resume = coroutine.resume
- local create = coroutine.create
- Task = function(func, ...)
- local self = setmetatable({
- type="task",
- coro=create(func),
- args={...},
- runtime=0,
- started_call=0,
- iteration=0,
- cancelled=false,
- done=false,
- is_error_handler=false,
- result=nil,
- after_done=nil
- }, {
- __call = function(self)
- assert(not self.cancelled, "Cannot resume a cancelled task")
- assert(not self.done, "Cannot resume a finished task")
- self.started_call = time()
- local done, result = resume(self.coro, unpack(self.args))
- local _end = time() - self.started_call
- self.runtime = self.runtime + _end
- local current = self
- while current.after_done do
- current = current.after_done
- current.runtime = current.runtime + _end
- end
- if (not done) or status(self.coro) == "dead" then
- self.done = true
- self.result = {done, result}
- end
- return done, result
- end
- })
- self.get_result = function()
- assert(self.done, "The task has not finished yet")
- assert(self.result[1], self.result[2])
- return unpack(result, 2)
- end
- self.real_runtime = function()
- return time() - self.started_call + self.runtime
- end
- return self
- end
- end
- local Loop
- do
- local time = os.time
- local unpack = table.unpack
- local remove = table.remove
- local yield = coroutine.yield
- Loop = function()
- local self = {
- max_runtime=10,
- iteration_cooldown=0,
- remove_later=0,
- iteration_no=0,
- last_accepted=0,
- used_runtime=0,
- tasks={},
- waiting={},
- current_task=nil,
- accept_faster=true,
- error_handler=function(msg)
- print("An error happened.")
- print(msg)
- end
- }
- self.add_task = function(task)
- self.tasks[#self.tasks + 1] = task
- end
- self.sleep = function(sleep_for)
- if not sleep_for then
- self.waiting[#self.waiting + 1] = {time(), self.current_task}
- else
- self.waiting[#self.waiting + 1] = {time() + sleep_for, self.current_task}
- end
- yield()
- end
- self.power_nap = function()
- self.add_task(self.current_task)
- yield()
- end
- self._accept_iteration = function(start, max)
- for index = self.remove_later, 1, -1 do
- remove(self.tasks, index)
- end
- self.remove_later = 0
- for index = #self.waiting, 1, -1 do
- if time() >= self.waiting[index][1] then
- self.tasks[#self.tasks + 1] = self.waiting[index][2]
- remove(self.waiting, index)
- end
- end
- local index = 0
- while ((time() - start) < max) and #self.tasks > index do
- index = index + 1
- local task = self.tasks[index]
- self.current_task = task
- if (not task.cancelled) and (not task.done) then
- task.iteration = self.iteration_no
- local task_done, task_result = task()
- if not task_done then
- if task.is_error_handler then
- error("The error handler threw an error: " .. task_result)
- else
- local t = Task(self.error_handler, task_result)
- t.is_error_handler = true
- self.tasks[#self.tasks + 1] = t
- end
- end
- if not task.done then
- if type(task_result) == "table" and task_result.type == "task" then
- task_result.after_done = task
- self.tasks[#self.tasks + 1] = task_result
- end
- end
- end
- self.remove_later = self.remove_later + 1
- if (task.done or task.cancelled) then
- if task.after_done then
- task.after_done.args = task.result
- self.tasks[#self.tasks + 1] = task.after_done
- end
- end
- end
- self.iteration_no = self.iteration_no + 1
- end
- self.run_tasks = function(start)
- local start = (not start) and time() or start
- if self.accept_faster then
- local do_reset = false
- if start - self.last_accepted >= self.iteration_cooldown then
- do_reset = true
- self.used_runtime = 0
- end
- local used = (time() - start + self.used_runtime)
- if used < self.max_runtime then
- local accept_start = time()
- self._accept_iteration(start, self.max_runtime - used)
- self.used_runtime = used + (time() - accept_start)
- if do_reset then
- self.last_accepted = time()
- end
- end
- elseif start - self.last_accepted >= self.iteration_cooldown then
- self._accept_iteration(start, self.max_runtime)
- end
- end
- return self
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement