how to simulate correctly threads with coroutine

Viewed 104

I was trying to create a thing that which can create some threads to work together. Do i missing? Codes can work together sequentially. I wrote this code

local Framework = {}
local threads = {}

local function has_value (tab, val)
    for index, value in ipairs(tab) do
        if value == val then
            return true
        end
    end

    return false
end

Framework.Wait = function(n)
  local t0 = os.clock()
   while os.clock() - t0 <= n do
   end
end

Framework.CreateThread = function(f)
  local thread = coroutine.create(f)
  table.insert(threads, thread)
  local index={}
  for k,v in pairs(threads) do
     index[v] = k
  end
  if threads[index[thread] + 1] then
    coroutine.yield(threads[index[thread] + 1])
  end
end

Framework.CreateThread(function()
  print("ok")
end)

Framework.CreateThread(function()
  while(true) do
    Framework.Wait(0.4)
    print("bot")
  end
end)

Framework.CreateThread(function()
  while(true) do
    Framework.Wait(0.4)
    print("got")
  end
end)

while(true) do
  Framework.Wait(0.1)
  for i = 1, #threads do
      coroutine.resume(threads[i])
  end
end

but it returns me not as expected. these are what it returns:

lua test.lua
ok
bot
bot
bot
bot
bot
bot
bot
bot
bot

these are expected:

ok
bot
got
bot
got
bot
got
....

or do i need c functions to do this? I can't get the algorithm to create in my head.

2 Answers
 while(true) do
    Framework.Wait(0.4)
    print("bot")
 end

You're stuck in this infinite loop. It will wait and print forever. You need to yield.

Coroutines do not run in parallel, therefore you need to yield the current one so the next one can run. A perfect time for a yield is the Framework.wait() function. We yield and return the time to wait. The thread scheduler (note the changes) then takes care of the times.

local Framework = {}
local threads = {}
local sleepUntil = {}

Framework.Wait = function(n)
  coroutine.yield(n)
end

Framework.CreateThread = function(f)
  local thread = coroutine.create(f)
  table.insert(threads, thread)
  table.insert(sleepUntil, 0)
  local index={}
  for k,v in pairs(threads) do
     index[v] = k
  end
  if threads[index[thread] + 1] then
    coroutine.yield(threads[index[thread] + 1])
  end
end

Framework.CreateThread(function()
  print("ok")
end)

Framework.CreateThread(function()
  while(true) do
    Framework.Wait(0.4)
    print("bot")
  end
end)

Framework.CreateThread(function()
  while(true) do
    Framework.Wait(0.4)
    print("got")
  end
end)

while(true) do
  for i = 1, #threads do
    if os.clock() > sleepUntil[i] then
      local continue, sleep = coroutine.resume(threads[i])
      if continue and sleep then
        sleepUntil[i] = os.clock() + sleep
      end
     end  
  end
end
Related