lua-users home
lua-l archive

RE: Lua and preemptive scheduling for coroutines

[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

AltStyle によって変換されたページ (->オリジナル) /