; Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees. See file COPYING. ; Locks (= semaphores) ; Each lock has: ; The owning thread's uid, or #f if not locked. The uid can be used ; to aid debugging without introducing the overhead of a weak pointer ; to the actual thread (a non-weak pointer would introduce an unfortunate ; circularity involving the locks and finalizers of ports). ; A queue of waiting threads (define-record-type lock :lock (really-make-lock owner-uid queue uid) lock? (owner-uid lock-owner-uid set-lock-owner-uid!) (queue lock-queue) (uid lock-uid)) ; for debugging (define *lock-uid* 0) (define (make-lock) (let ((uid *lock-uid*)) (set! *lock-uid* (+ uid 1)) (really-make-lock #f (make-queue) uid))) (define (obtain-lock lock) (with-interrupts-inhibited (lambda () (if (lock-owner-uid lock) (block-on-queue (lock-queue lock)) (set-lock-owner-uid! lock (thread-uid (current-thread))))))) (define (maybe-obtain-lock lock) (with-interrupts-inhibited (lambda () (if (lock-owner-uid lock) #f (begin (set-lock-owner-uid! lock (thread-uid (current-thread))) #t))))) (define (obtain-lock-multiple . all-locks) (with-interrupts-inhibited (lambda () (let loop ((locks all-locks)) (cond ((null? locks) (for-each (lambda (lock) (enqueue-thread! (lock-queue lock) (current-thread))) all-locks) (block)) ((lock-owner-uid (car locks)) (loop (cdr locks))) (else (set-lock-owner-uid! (car locks) (thread-uid (current-thread))))))))) ; Returns #t if the lock has no new owner. (define (release-lock lock) (with-interrupts-inhibited (lambda () (let ((queue (lock-queue lock))) (cond ((maybe-dequeue-thread! queue) => (lambda (next) (set-lock-owner-uid! lock (thread-uid next)) (make-ready next) #f)) (else (set-lock-owner-uid! lock #f) #t))))))