lock.scm 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Locks (= semaphores)
  3. ; Each lock has:
  4. ; The owning thread, or #f if not locked. We use the owning thread instead
  5. ; of #t as an aid to debugging.
  6. ; A queue of waiting threads
  7. (define-synchronized-record-type lock :lock
  8. (really-make-lock owner queue uid)
  9. (owner)
  10. lock?
  11. (owner lock-owner set-lock-owner!)
  12. (queue lock-queue)
  13. (uid lock-uid)) ; for debugging
  14. (define lock-uid (list 0))
  15. (define (next-uid)
  16. (atomically
  17. (let ((uid (provisional-car lock-uid)))
  18. (provisional-set-car! lock-uid (+ uid 1))
  19. uid)))
  20. (define (make-lock)
  21. (really-make-lock #f (make-queue) (next-uid)))
  22. (define (obtain-lock lock)
  23. (with-new-proposal (lose)
  24. (or (cond ((lock-owner lock)
  25. (maybe-commit-and-block-on-queue (lock-queue lock)))
  26. (else
  27. (set-lock-owner! lock (current-thread))
  28. (maybe-commit)))
  29. (lose))))
  30. ; Returns #T if the lock is obtained and #F if not. Doesn't block.
  31. (define (maybe-obtain-lock lock)
  32. (with-new-proposal (lose)
  33. (cond ((lock-owner lock) ; no need to commit - we have only done
  34. #f) ; a single read
  35. (else
  36. (set-lock-owner! lock (current-thread))
  37. (or (maybe-commit)
  38. (lose))))))
  39. ; Returns #t if the lock has no new owner.
  40. (define (release-lock lock)
  41. (with-new-proposal (lose)
  42. (let ((next (maybe-dequeue-thread! (lock-queue lock))))
  43. (cond (next
  44. (set-lock-owner! lock next)
  45. (or (maybe-commit-and-make-ready next)
  46. (lose)))
  47. (else
  48. (set-lock-owner! lock #f)
  49. (or (maybe-commit)
  50. (lose)))))))
  51. (define (with-lock lock thunk)
  52. (dynamic-wind
  53. (lambda () (obtain-lock lock))
  54. thunk
  55. (lambda () (release-lock lock))))