|
Yes, I said "local variables" but I
was mentally including the function arguments too. I realize now that
calling the object returned by coroutine.create() a "thread" was
probably an unfortunate choice. As you pointed out, threads allow
parallel or pseudo-parallel execution, while there is no parallelism
with coroutines. As an aside, it is possible to implement a cooperative multitasking system with coroutines. One would need one coroutine for each task plus a scheduler. The scheduler is a loop that keeps picking the first task from a queue of ready tasks (if any) and resumes it. The ready queue and other task queues could be sorted on priority or just FIFO. function scheduler() while true do current_task = pop_front(ready_queue) if current_task then coroutine.resume(current_task) end end end end One can easily write primitives that would allow tasks to yield, block while waiting for some event and be awakened by an event, for example: function yield() push_back(ready_queue, current_task) coroutine.yield() end function wait(event) push_back(task_queue[event], current_task) coroutine.yield() end function signal(event) local task = pop_front(task_queue[event]) if task then push_back(ready_queue, task) end -- (Only for systems that support task priorities:) -- If task has higher priority than current_task, call -- coroutine.yield() here so the scheduler may resume it. end Based on these simple primitives things like semaphores, mutexes, message-passing etc. can be easily devised. I will try to write a multitasking module on these lines. As you pointed out, a system like this would emulate cooperative multithreading faithfully in a single processor environment only, since only one coroutine can be active at any time, while a multi-processor system can run one thread on each processor. Regards, Hugo David Kastrup escribió: Hugo Etchegoyen <hetchegoyen@hasar.com> writes:If I understood well, then one might say that resuming is like calling and yielding is like returning, the only difference being that the callee keeps the values of its local variables between invocations, and each time it is called it starts executing at the instruction following the last yield. Right?And it keeps its whole call stack, too. You can yield in the middle of a called function. Just like the caller (so coroutines are an emancipation of subroutines, but there remain subtle differences). Basically right. --
Ing.
Hugo Eduardo Etchegoyen Compañía
Hasar | Grupo
Hasar |