mutexやcondition variableのような同期機構ではなく、チャネル通信などの機構を使えということなのだと思うが、ロックを使ったほうが素直に実装できる場合もある。
幸いセマフォはあるようなので、セマフォでmutexやcondition variableを次のように書いた。
;;; mutex
(define (make-mutex)
(make-semaphore 1))
(define (mutex-lock! m)
(semaphore-wait m))
(define (mutex-unlock-primitive! m)
(semaphore-post m))
(define (mutex-unlock! m . rest)
(let ((condvar (if (null? rest) #f (car rest))))
(mutex-unlock-primitive! m)
(when condvar
(condition-variable-wait! condvar))))
;;; gate
(define (make-gate)
(make-semaphore 0))
(define (gate-wait! g)
(semaphore-wait g))
(define (gate-signal! g)
(semaphore-post g))
;;; condition variable
(define (make-condition-variable)
(list 'condition-variable '() (make-mutex)))
(define (condition-variable-gates cv)
(list-ref cv 1))
(define (condition-variable-mutex cv)
(list-ref cv 2))
(define (condition-variable-clear-gates! cv)
(set-car! (cdr cv) '() ))
(define (condition-variable-put-gates! cv val)
(set-car! (cdr cv)
(cons val (condition-variable-gates cv))))
(define (condition-variable-wait! cv)
(let ((mutex (condition-variable-mutex cv))
(gates (condition-variable-gates cv))
(new-gate (make-gate)))
(mutex-lock! mutex)
(condition-variable-put-gates! cv new-gate)
(mutex-unlock-primitive! mutex)
(gate-wait! new-gate)))
(define (condition-variable-signal! cv)
(let ((mutex (condition-variable-mutex cv))
(gates (condition-variable-gates cv)))
(mutex-lock! mutex)
(for-each (lambda (g) (gate-signal! g))
gates)
(condition-variable-clear-gates! cv)
(mutex-unlock-primitive! mutex)))
condition variableは使い捨てのmutexを用いて実装している。
これで、同期に関してSRFI 18で定められた手続きが使える。