|
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/source/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.
It does highlight the fact that i/o bound actors have natural yeild points, and non-i/o bound actors don't. If the client code is written so as to separate i/o bound and cpu-bound tasks then this kind of structure makes a lot of sense (and cpu-bound tasks can be treated as a blocking resource like i/o by most of the code). Consequences:
An i/o bound task (event handler) that doesn't yeild "real fast" is faulty and should be killed.
A cpu bound task that doesn't yeild is "uncooperative" and considered unacceptable.
If you had a "kill coroutine after timeout" primitive (ie the one that injects an error into the coroutine) then you could apply time constraints on both event handlers and worker tasks and kill any non-compliant tasks.
Another approach, if you have a way to interrupt worker tasks, is to execute the i/o bound tasks at "interrupt level" while a worker is still running.
The question remains: is it viable to implement the "interrupt and inject" primitive?
Ross.