ayya
ayya

Reputation: 71

how to simulate correctly threads with coroutine

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.

Upvotes: 2

Views: 413

Answers (2)

Luke100000
Luke100000

Reputation: 1554

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

Upvotes: 1

Piglet
Piglet

Reputation: 28950

 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.

Upvotes: 1

Related Questions