Advertisement
Piorjade

OpenComputers- Multitasking API

Mar 24th, 2017
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.48 KB | None | 0 0
  1. --[[
  2.         Multitasking API for OpenComputers
  3.        
  4.         Basic steps:
  5.         create a new tasklist with multitask.createTasklist() (it returns a table, which is the tasklist)
  6.         create tasks using multitask.createTask([tasklist], [string], [string], [environment], [boolean])
  7.         (yes, the function that you give to createTask must be in string form as setfenv() doesn't exist anymore and bytecode loading is forbidden in opencomputers)
  8.         run all the tasks using multitask.runAll([tasklist])
  9.         (NOTE: tasks need to yield, they get killed automatically otherwise)
  10.         (NOTE: currently you NEED the keyboard and event API for it to work)
  11.  
  12.         Functions that are added or edited for tasks:
  13.         - event.pull [edited]: basically just yields the task so "multitasking" actually works
  14.         - sleep([number]) [added]: lets the task sleep for a certain time (same as os.sleep(), but only for the task)
  15.  
  16.         How to use:
  17.         - Load the library via require
  18.         - Enjoy
  19.  
  20.         WARNING: This is a testing build and may cause lag or bad performance
  21.        
  22.     ~Piorjade
  23. ]]
  24.  
  25. local multitask = {}
  26.  
  27. function multitask.createTask(tasklist, name, func, env, disableG)
  28.     if not env then env = _G end
  29.     if type(func) ~= "string" then return false, "table, string, code(string), environment expected" end
  30.     if type(tasklist) ~= "table" then return false, "table, string, code(string), environment expected" end
  31.     local event = require("event")
  32.     tasklist[name] = nil
  33.     f = func
  34.     env.event = {}
  35.     for a, b in pairs(event) do
  36.         env.event[a] = b
  37.     end
  38.     if disableG then env._G = env end
  39.     function env.event.pull(filtr, ...)
  40.         local args = {...}
  41.         local timeout = nil
  42.         if type(args[1]) == "number" then timeout = args[1] else timeout = nil end
  43.         if not timeout then
  44.             local tab = nil
  45.             repeat
  46.                 tab =  {coroutine.yield()}
  47.                 if tab ~= nil and tab[1] == (filtr or tab[1]) then
  48.                     local notFound = false
  49.                     for a, b in ipairs(args) do
  50.                         if b ~= nil and tab[a] ~= b then
  51.                             notFound = true
  52.                             break
  53.                         end
  54.                     end
  55.                     if not notFound then
  56.                         return table.unpack(tab)
  57.                     end
  58.                 end
  59.             until tab ~= nil
  60.             return tab
  61.         else
  62.             local running = true
  63.             local timer = event.timer(timeout, function() running = false end)
  64.             local tab = nil
  65.             while running do
  66.                 tab = coroutine.yield()
  67.                 if tab ~= nil and tab[1] == (filtr or tab[1]) then
  68.                     local notFound = false
  69.                     for a, b in ipairs(args) do
  70.                         if b ~= nil and tab[a] ~= b then
  71.                             notFound = true
  72.                             break
  73.                         end
  74.                     end
  75.                     if not notFound then
  76.                         return table.unpack(tab)
  77.                     end
  78.                 end
  79.             end
  80.             return nil
  81.         end
  82.     end
  83.     function env.programQuit()
  84.         tasklist[name].dead = true
  85.         coroutine.yield()
  86.     end
  87.     function env.sleep(count)
  88.         local running = true
  89.         function stopRunning()
  90.             running = false
  91.         end
  92.         local timer = event.timer(count, stopRunning)
  93.         while running do
  94.             coroutine.yield()
  95.         end
  96.     end
  97.     local func, err = load(f, "="..name, "bt", env)
  98.     if not func then return false, err else
  99.     tasklist[name] = {}
  100.     tasklist[name].task = coroutine.create(func)
  101.     tasklist[name].dead = false
  102.     return true
  103.     end
  104. end
  105.  
  106. function multitask.quit(taskName)
  107.     local computer = require("computer")
  108.     computer.pushSignal("multitask_quit", taskName)
  109. end
  110.  
  111. function multitask.runAll(tasklist)
  112.     local evt = {}
  113.     local event = require("event")
  114.     while true do
  115.         for name, task in pairs(tasklist) do
  116.             if type(task) == "table" and task.task and tasklist[name].dead ~= true and name ~= "log" and name ~= "errorLog" then
  117.                 local ok, err = coroutine.resume(task.task, table.unpack(evt))
  118.                 if not ok then
  119.                     tasklist[name].dead = true
  120.                     table.insert(tasklist.errorLog, err)
  121.                 end
  122.                 if coroutine.status(task.task) == "dead" then
  123.                     tasklist[name].dead = true
  124.                     table.insert(tasklist.log, "Process died: "..name)
  125.                 end
  126.             end
  127.         end
  128.         for a, b in pairs(tasklist) do
  129.             if type(b) == "table" and b.dead then
  130.                 tasklist:killTask(a)
  131.             end
  132.         end
  133.         evt = {event.pull(0.1)}
  134.         if evt[1] == "multitask_quit" then
  135.             if evt[2] then
  136.                 tasklist[evt[2]] = nil
  137.             else
  138.                 break
  139.             end
  140.         end
  141.        
  142.         local counter = 0
  143.         for each, task in pairs(tasklist) do
  144.             counter = counter + 1
  145.         end
  146.         if counter == 0 then break end
  147.     end
  148. end
  149.  
  150. function multitask.createTasklist()
  151.     local tasklist = {}
  152.     tasklist.log = {}
  153.     tasklist.errorLog = {}
  154.     function tasklist:clearLog()
  155.         self.errorLog = {}
  156.         self.log = {}
  157.     end
  158.     function tasklist:killTask(name)
  159.         if name then
  160.             self[name] = {}
  161.         end
  162.     end
  163.     return tasklist
  164. end
  165.  
  166. return multitask
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement