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
Gerente Dto. Software de Base
Compañía
Hasar | Grupo
Hasar
Marcos Sastre y José Ingenieros
El Talar. Pacheco
[B1618CSD] Buenos Aires. Argentina
Tel [54 11] 4117 8900 | Fax [54 11] 4117 8998
E-mail: hetchegoyen@hasar.com
Visítenos en: www.hasar.com
Información legal y política de
confidencialidad: www.grupohasar.com/disclaimer