lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



> -----Original Message-----
> From: lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org] On
> Behalf Of Ross Bencina
> Sent: zaterdag 30 maart 2013 4:58
> To: Lua mailing list
> Subject: Re: Lua and preemptive scheduling for coroutines
> 
> 
> On 29/03/2013 10:25 PM, Thijs Schreijer wrote:
>  >> [Ross Bencina wrote]
> >> My (completely idiosyncratic) view is that actors with atomic
> >> run-to-
> >>> completion actions are a nice model. That way thread switch only
> >>> happens in the scheduler. Actors can be raw handers or state
> >>> machines (FSMs, HFSMs) and communicate (only) via non-blocking
> >>> queues. Miro Samek has a nice practical book on this.
> >>>
> >>> The main problem in implementing this in Lua would be supporting
> >>> long running computation, (if you need to). Plus you need fully
> >>> async i/o, but that's not so hard to get these days (eg luvit)
> >>>
> > Somethings like this
> >
> example?https://github.com/Tieske/CopasTimer/blob/tasks_as_coroutines/sour
> ce/copas/timer.lua#L254
> >
> >
> > See the queue:pop() and queue:pause() calls
> > I'm rewriting the CopasTimer module to work more coroutine oriented.
> > I think you'll find similar code in the Sierra Wireless scheduler.
> 
> 
> If I understand that code correctly it's running worker tasks at "idle"
> priority using cooperative scheduling (explicit yeild via queue:pause()).
> 
> That certainly solves the "supporting long running computation" problem,
> but it uses explicit cooperation (queue:pause()), so doesn't quite fit
> with the discussion of being fail-safe to untrusted code.

Just did a test. Try this code. The 'checker' will allow to run a coroutine for 1 second. A coroutine 'coro' is scheduled and runs for 2 seconds. It does work, the coro gets interrupted after 1 second and the code terminates.

local socket = require("socket")
local t = socket.gettime()
local i = 0
local checkcount=0

local corof1 = function()
  -- will exit after 2 seconds
  while t+2>socket.gettime() do
    i = i + 1
  end
  return "Loop completed"
end

local checker = function()
  checkcount = checkcount+1 
  -- will kill the coro after 1 second
  if t+1<socket.gettime() then 
    print("timeout")
    error("timeout")  
  end
end

local coro = coroutine.create(corof1)

debug.sethook(coro, checker, "l", 5000)
print(coroutine.resume(coro))

How it works: See [1], which states;
    "Inside a hook, you can call getinfo with level 2 
    to get more information about the running function 
    (level 0 is the getinfo function, and level 1 is 
    the hook function),"
So this means that the debughook runs on the executionstack of the coroutine. The error thrown by the 'checker' function in case of a timeout will put the coroutine in an "error state" and force it to die.

What you can't catch, is blocking calls on c level, eg. blocking IO functions.

I need to find some time, but then I'll wrap this in a general module probably. I certainly have some use for it myself.

Thijs

[1] http://www.lua.org/manual/5.1/manual.html#pdf-debug.sethook