CC: Tweaked

CC: Tweaked

59M Downloads

Add a classical "thread" library

JWTHDYTWA opened this issue ยท 1 comments

commented

There's already a library for multithreading, "parallel", but it's awkward. You have to just split your program at some time. Is it possible to add good ol' threads? Where you just make a new thread and continue.

commented

So just in case you're not aware, this is definitely possible to do yourself with some slight modifications to the parallel API. Here is a pretty basic version I've used in a couple of projects:

thread.lua
local expect = require "cc.expect"

local function checked_resume(co, ...)
  local ok, result = coroutine.resume(co, ...)
  if not ok then error(debug.traceback(co, result), 0) end
  return result
end

local function create_runner(init)
  expect(1, init, "function")

  local active, active_n = {}, 0

  local function spawn(fn, ...)
    expect(1, fn, "function")

    local co = coroutine.create(fn)
    local result = checked_resume(co, ...)
    if coroutine.status(co) ~= "dead" then
      active_n = active_n + 1
      active[active_n] = { co = co, filter = result or false }
    end
  end

  spawn(init, spawn)

  while active_n > 0 do
    local event = table.pack(os.pullEventRaw())
    local event_name = event[1]

    for i = active_n, 1, -1 do
      local task = active[i]
      if not task.filter or task.filter == event_name or event_name == "terminate" then
        local filter = checked_resume(task.co, table.unpack(event, 1, event.n))
        if coroutine.status(task.co) == "dead" then
          table.remove(active, i)
          active_n = active_n - 1
        else
          task.filter = filter or false
        end
      end
    end
  end
end

-- Create a parallel runner
create_runner(function(spawn)
  -- Spawn a new thread
  spawn(function()
    for i = 1, 3 do print("A", i) sleep(0.5) end
  end)

  -- And another one
  spawn(function()
    for i = 1, 5 do print("B", i) sleep(0.5) end
  end)
end)

As far as adding this to CC:T itself, this is where it gets much tricker. We've discussed this several times in the past (#54, #280), and it's honestly really hard to find a good API here - there's a lot of different use-cases, and I've not really found something which works for everyone.