Exercises in this lecture   Go to the notes, in which this exercise belongs -- Keyboard shortcut: 'u'   Alphabetic index   Course home   

Exercise solution:
A variant of seesaw that completes both threads


Here is my new version of seesaw:

(define (seesaw thread-1 thread-2) (seesaw-1 thread-1 thread-2 'doing 'doing #f #f)) (define (seesaw-1 thread-1 thread-2 thread-1-status thread-2-status val-1 val-2) (cond ((and (eqv? thread-1-status 'done) (eqv? thread-2-status 'done)) (list val-1 val-2)) ((and (eqv? thread-1-status 'done) (eqv? thread-2-status 'doing)) (let* ((next-thread (call (tag-value thread-2))) (new-val-2 (if (eqv? (tag-of next-thread) 'done) (tag-value next-thread) val-2))) (seesaw-1 thread-1 next-thread 'done (tag-of next-thread) val-1 new-val-2))) ((and (eqv? thread-1-status 'doing) (eqv? thread-2-status 'done)) (let* ((next-thread (call (tag-value thread-1))) (new-val-1 (if (eqv? (tag-of next-thread) 'done) (tag-value next-thread) val-1))) (seesaw-1 next-thread thread-2 (tag-of next-thread) 'done new-val-1 val-2))) (else ; both threads have doing stats - advance both of them (let ((next-thread-1 (call (tag-value thread-1))) (next-thread-2 (call (tag-value thread-2)))) (seesaw-1 next-thread-1 next-thread-2 (tag-of next-thread-1) (tag-of next-thread-2) (tag-value next-thread-1) (tag-value next-thread-2) )))))

As an invariant, thread-1-status is the actual status of thread-1, and val-1 is the actual value produced by thread-1 (when ay). val-1 is only defined in the case where thread-status-1 is done. The same holds for thread-2.

There are four cases - all possible combinations of done/doing for thread-1 and thread-2. In the case where both thread-1 and thread-2 are doing, I execute a step in both of them. You may not like this, as this is different from the original version of seesaw.