chibi-scheme/lib/chibi/channel.scm
2015-01-26 08:06:59 +09:00

44 lines
1.4 KiB
Scheme

;; channel.scm -- thread-safe channel (FIFO) library
;; Copyright (c) 2012 Alex Shinn. All rights reserved.
;; BSD-style license: http://synthcode.com/license.txt
(define-record-type Channel
(%make-channel mutex condvar front rear)
channel?
(mutex channel-mutex channel-mutex-set!)
(condvar channel-condvar channel-condvar-set!)
(front channel-front channel-front-set!)
(rear channel-rear channel-rear-set!))
(define (make-channel)
(%make-channel (make-mutex) (make-condition-variable) '() '()))
(define (channel-empty? chan)
(null? (channel-front chan)))
(define (channel-send! chan obj)
(mutex-lock! (channel-mutex chan))
(let ((new (list obj))
(rear (channel-rear chan)))
(channel-rear-set! chan new)
(cond
((pair? rear)
(set-cdr! rear new))
(else ; sending to empty channel
(channel-front-set! chan new)
(condition-variable-broadcast! (channel-condvar chan)))))
(mutex-unlock! (channel-mutex chan)))
(define (channel-receive! chan)
(mutex-lock! (channel-mutex chan))
(let ((front (channel-front chan)))
(cond
((null? front) ; receiving from empty channel
(mutex-unlock! (channel-mutex chan) (channel-condvar chan))
(channel-receive! chan))
(else
(channel-front-set! chan (cdr front))
(if (null? (cdr front))
(channel-rear-set! chan '()))
(mutex-unlock! (channel-mutex chan))
(car front)))))