Advertisement
szymski

Untitled

Jun 17th, 2017
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.39 KB | None | 0 0
  1. --@name Task Library 2
  2. --@author Szymekk
  3.  
  4. --------------------------------------
  5. -- Task class
  6. --------------------------------------
  7.  
  8. local task = { }
  9. task.__index = task
  10.  
  11. function task:init(func)
  12. self._func = func
  13.  
  14. self._running = false -- The task has been run once and haven't finished
  15. self._finished = false -- The has returned - self.result should not be nil
  16. self.result = nil -- Values retured from the task as a table
  17.  
  18. self._parent = nil -- Waiting parent of the task, should be awoken after the current task finishes
  19.  
  20. self._async = nil -- Async object of the task, when true - parent should be awoken
  21.  
  22. self._coroutine = coroutine.create(function(...)
  23. local result = { func(...) }
  24.  
  25. if self._async then
  26. result = { coroutine.yield() } -- Wait for async:release()
  27. self._async = nil
  28.  
  29. self.result = result
  30. self._running = false
  31. self._finished = true
  32.  
  33. -- Resume the parent
  34. if self._parent then
  35. local parent = self._parent
  36.  
  37. self._async = nil
  38. self._parent = nil
  39.  
  40. local prevTask = tasks.current
  41.  
  42. tasks.current = parent
  43. coroutine.resume(parent._coroutine)
  44. tasks.current = prevTask
  45. end
  46. end
  47.  
  48. return unpack(returned)
  49. end)
  50. end
  51.  
  52. --- Runs or resumes the task
  53. function task:run(...)
  54. -- Waiting for an asynchronic task - it's resumed somewhere else
  55. if self._waiting then
  56. return
  57. end
  58.  
  59. if self._async then
  60. return
  61. end
  62.  
  63. if self._finished then
  64. error("Cannot run finished task")
  65. end
  66.  
  67. -- The task is running for the first time
  68. if not self._running then
  69. self._running = true
  70. end
  71.  
  72. local prevTask = tasks.current
  73.  
  74. tasks.current = self
  75. local result
  76. local args = { ... }
  77. pcall(function() -- Temporary workaround
  78. result = { coroutine.resume(self._coroutine, unpack(args)) }
  79. end)
  80. tasks.current = prevTask
  81.  
  82. -- The task could become async
  83. if self._async and self._async ~= true then
  84. return
  85. end
  86.  
  87. -- When task finished the work
  88. if coroutine.status(self._coroutine) == "dead" then
  89. self.result = result
  90. self._running = false
  91. self._finished = true
  92. end
  93. end
  94.  
  95. task.resume = task.run
  96.  
  97. --- Makes the current task pause until this task finishes
  98. function task:wait(...)
  99. local parent = tasks.current
  100. self._parent = parent
  101.  
  102. self:run(...)
  103.  
  104. -- The task haven't finished yet - it's probably asynchronic
  105. if not self._finished then
  106. parent._waiting = true
  107. coroutine.yield()
  108. parent._waiting = false
  109. end
  110.  
  111. self._parent = nil
  112.  
  113. return unpack(self.result)
  114. end
  115.  
  116. --------------------------------------
  117. -- Creation
  118. --------------------------------------
  119.  
  120. tasks = { }
  121.  
  122. tasks.current = nil -- Currently running task
  123.  
  124. function tasks.new(func)
  125. local tbl = { }
  126. setmetatable(tbl, task)
  127. tbl:init(func)
  128. return tbl
  129. end
  130.  
  131. --------------------------------------
  132. -- Async
  133. --------------------------------------
  134.  
  135. local async = { }
  136. async.__index = async
  137.  
  138. function async:init(task)
  139. self._task = task
  140. end
  141.  
  142. --- Finishes an asynchronic task.
  143. --- Any parameters passed to this function
  144. --- will be the task's result.
  145. function async:release(...)
  146. local args = { ... }
  147.  
  148. local prevTask = tasks.current
  149.  
  150. tasks.current = self._task
  151. pcall(function()
  152. coroutine.resume(self._task._coroutine, unpack(args)) -- This function errors and won't go further, pcall is a temporary fix
  153. end)
  154. tasks.current = prevTask
  155. end
  156.  
  157. function async.new(...)
  158. local tbl = { }
  159. setmetatable(tbl, async)
  160. tbl:init(...)
  161. return tbl
  162. end
  163.  
  164. --- Makes the current task asynchronic.
  165. --- It won't finish as soon as its function returns,
  166. --- but an async object will be returned - calling
  167. --- async:release(toReturn) will finish the task.
  168. function tasks.makeAsync()
  169. local asyncObj = async.new(tasks.current)
  170. tasks.current._async = asyncObj
  171.  
  172. return asyncObj
  173. end
  174.  
  175. --------------------------------------
  176. -- Testing
  177. --------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement