Next: , Up: iklib coroutines   [Index]


6.11.1 Usage examples for coroutines

Coroutines are created by the function coroutine; a coroutine in execution can yield control to the next coroutine with the function yield. It is possible to enter a loop that runs all the coroutines until all of them are finished with the function finish-coroutines.

All the examples in this section are to be considered as Scheme programs after the prelude:

#!r6rs
(import (vicare))

(set-port-buffer-mode! (current-output-port)
                       (buffer-mode line))

which allows the intertwining of coroutines to be seen by displaying strings on the current output port.

Two coroutines

The following example runs two coroutines and waits for them to finish:

(coroutine
    (lambda ()
      (display "one 1\n")
      (yield)
      (display "one 2\n")
      (yield)
      (display "one 3\n")))

(coroutine
    (lambda ()
      (display "two 1\n")
      (yield)
      (display "two 2\n")
      (yield)
      (display "two 3\n")))

(finish-coroutines)

the output is:

one 1
two 1
one 2
two 2
one 3
two 3

We see that to exit a coroutine we just return from its start function.

The main routine and a subroutine

We can always consider the ordinary control flow of a program as a coroutine, the main routine; so the following program produces output similar to the one above:

(coroutine
    (lambda ()
      (display "sub 1\n")
      (yield)
      (display "sub 2\n")
      (yield)
      (display "sub 3\n")))

;;This runs in the main routine.
(display "main 1\n")
(yield)
(display "main 2\n")
(yield)
(display "main 3\n")

(finish-coroutines)

the output is:

sub 1
main 1
sub 2
main 2
sub 3
main 3

Main routine alone

It is perfectly all right to call yield and finish-coroutines from the main routine even when there are no subroutines:

(display "main 1\n")
(yield)
(display "main 2\n")
(yield)
(display "main 3\n")
(finish-coroutines)

the output of this program is just:

main 1
main 2
main 3

Finishing coroutines

It is possible to call finish-coroutines from any coroutine, but we must be careful because if we let the main routine exit before all the routines are finished some computation will not take place. In the following program the subroutine has more steps than the main routine:

(coroutine
    (lambda ()
      (display "sub 1\n")
      (yield)
      (display "sub 2\n")
      (yield)
      (display "sub 3\n")
      (yield)
      (display "sub 4\n")
      (yield)
      (display "sub 5\n")
      (finish-coroutines)))

;; This runs in the main routine.
(display "main 1\n")
(yield)
(display "main 2\n")
(yield)
(display "main 3\n")

and its output is:

sub 1
main 1
sub 2
main 2
sub 3
main 3

we see that ‘sub 4’ and ‘sub 5’ are not displayed.

Finish coroutines as exit hook

It can be useful to register finish-coroutines as exit hook, so that upon exiting the process all the pending coroutines are correctly terminated.

(coroutine
    (lambda ()
      (display "one 1\n")
      (yield)
      (display "one 2\n")
      (yield)
      (display "one 3\n")))

(coroutine
    (lambda ()
      (display "two 1\n")
      (yield)
      (display "two 2\n")
      (yield)
      (display "two 3\n")))

(exit-hooks (cons finish-coroutines (exit-hooks)))
(exit)

Next: , Up: iklib coroutines   [Index]