[並行計算][Scheme][Racket] SRFI 18のmutexとcondition variable
2011 年 11 月 9 日
コメントはありません
RacketはSRFI 18に対応していることになっているが、mutex-lock!やcondition-variable-signal!などどの手続きはrequireしても定義されない。
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で定められた手続きが使える。
最近のコメント