Christian Collberg
Department of Computer Science
University of Arizona
var us, cfs: coroutine;
coroutine update_screen() {
...
detach
loop {
... transfer(cfs) ...
}
}
coroutine check_file_system() { ... }
main () { ... }
coroutine check_file_system() {
...
detach
for all files do {
... transfer(cfs)
... transfer(cfs)
... transfer(cfs) ...
}
}
main () {
us := new update_screen();
cfs := new check_file_system();
transfer(us);
}
PROCEDURE NEWPROCESS( proc: PROC; (* The procedure *) addr: ADDRESS; (* The stack *) size: CARDINAL; (* The stack size *) VAR new: ADDRESS); (* The coroutine *) PROCEDURE TRANSFER( VAR source: ADDRESS; (* Current coroutine *) VAR destination: ADDRESS); (* New coroutine *)
VAR crparams: CoroutineParameters;
source: ADDRESS; (* current coroutine is called by this *)
newcr: ADDRESS; (* coroutine just created by NEWPROCESS *)
PROCEDURE Coroutine;
VAR myparams: CoroutineParameters;
BEGIN
myparams := crparams;
TRANSFER(newcr, source); (* return to calling coroutine *)
(* rest of coroutine *)
END Coroutine;
PROCEDURE Setup(params: CoroutineParameters; proc: PROC);
BEGIN
NEWPROCESS(proc, addr, size, newcr);
crparams := params; TRANSFER(source, newcr);
END Setup;
class Coroutine # Creates a coroutine. The associated block # does not run yet. def initialize(&block) # Starts the block. It's an error to call # this method on a coroutine that has # already been started. def start # Switches context to another coroutine. You # need to call this method on the current coroutine. def switch(coroutine)
... # Returns true if the associated block is # started and has not yet finished def running? # Returns true if the associated block is # finished def finished? end
$c1 = Coroutine::new do
for i in 'a'..'z' do
printf "%s ", i
$c1.switch($c2)
end
end
$c2 = Coroutine::new do
for i in 1..26 do
printf "%i ", i
$c2.switch($c1)
end
end
Running the example:
$c1.start printf "\n"yields the result
a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26
$result = 0
def iterate(arr,other)
c = Coroutine::new do
i = 0
while i < arr.length
$result = arr[i]
i += 1
c.switch(other)
end
end
return c
end
main = Coroutine::new do
a = [1,2,3]
iter = iterate(a,main)
while not iter.finished?
main.switch(iter)
printf "%i ", $result
end
printf "\n"
end
current_coroutine := ...
PC := ...
SP :=
transfer(C) {
push R1,R2,RA
*current_coroutine := SP
current_coroutine := C
SP := *C
pop R1,R2,RA
return
}