Back to lecture notes -- Keyboard shortcut: 'u'                      Lecture 3 - slide 38 : 43
 

; Producer consumer - a variant where the continuation of "the other coroutine" is 
; maintained in the state variable other-coroutine

(define (stop-value? x) (and (boolean? x) x))  
(define STOP-VALUE #t)
(define NO-CONTINUATION #f)

(define other-coroutine #f)                    

(define (exchange new)                         
  (let ((old-other other-coroutine))           
    (set! other-coroutine new)
    old-other))

(define (producer)
  (call-with-current-continuation
    (lambda (exit)
       (let ((producer-values (list 2 3 4 5 6)))  
         (letrec ((producer-iter 
                    (lambda (values)
                      (cond ((null? values) (other-coroutine STOP-VALUE))   
                            (else 
                              (let* ((new-consumer-continuation
                                      (call-with-current-continuation
                                       (lambda (here)
                                         (if other-coroutine
                                             ((exchange here) (car values)) 
                                             (exit here)))))) 
                                (producer-iter (cdr values))))))))
            (producer-iter (cons 'no-value producer-values)))))))

(define (consumer)
 (letrec ((consumer-processor (lambda (x) (* x x)))) 
  (call-with-current-continuation
    (lambda (exit)
      (letrec ((consumer-iter
                (lambda ()
                  (let* ((value-from-producer (call-with-current-continuation
                                         (lambda (here)
                                           ((exchange here) 'no-value)))) 
                         )
                    (if (stop-value? value-from-producer)
                        '()
                        (let ((processed-value (consumer-processor value-from-producer)))
                          (cons processed-value (consumer-iter))))))))
        (consumer-iter))))))


; Setup: Start producer first. Assign initial-producer-cont to other-coroutine.
(let ((initial-producer-cont (producer)))  
  (set! other-coroutine initial-producer-cont) 
  (consumer) 
)  ; => (4 9 16 25 36)