jar.scm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Mike Sperber
  3. ; Jars (multiple-assignment cells for use with threads)
  4. ; these are equivalent to ID-90 M-structures
  5. (define-synchronized-record-type jar :jar
  6. (really-make-jar priority queue value id)
  7. (priority value)
  8. jar?
  9. (priority jar-priority set-jar-priority!)
  10. (queue jar-queue)
  11. (value jar-value set-jar-value!)
  12. (id jar-id))
  13. (define the-empty-jar-value (list 'empty-jar))
  14. (define (empty-jar-value? thing)
  15. (eq? thing the-empty-jar-value))
  16. (define-record-discloser :jar
  17. (lambda (jar)
  18. (cons 'jar
  19. (if (jar-id jar)
  20. (list (jar-id jar))
  21. '()))))
  22. (define-record-type q-item :q-item
  23. (make-q-item trans-id cleanup-proc wrap-proc)
  24. q-item?
  25. (trans-id q-item-trans-id)
  26. (cleanup-proc q-item-cleanup-proc)
  27. (wrap-proc q-item-wrap-proc))
  28. (define (clean-and-enqueue! queue value)
  29. (clean-queue-head! queue)
  30. (enqueue! queue value))
  31. (define (clean-and-dequeue! queue)
  32. (let loop ()
  33. (if (queue-empty? queue)
  34. #f
  35. (let ((front (dequeue! queue)))
  36. (if (trans-id-cancelled? (q-item-trans-id front))
  37. (loop)
  38. front)))))
  39. (define (clean-queue-head! queue)
  40. (let loop ()
  41. (if (not (queue-empty? queue))
  42. (let ((front (queue-head queue)))
  43. (if (trans-id-cancelled? (q-item-trans-id front))
  44. (begin
  45. (dequeue! queue)
  46. (loop)))))))
  47. (define (make-jar . id-option)
  48. (really-make-jar 0
  49. (make-queue)
  50. the-empty-jar-value
  51. (if (null? id-option)
  52. #f
  53. (car id-option))))
  54. (define (jar-take-rv jar)
  55. (make-base
  56. (lambda ()
  57. (cond
  58. ((empty-jar-value? (jar-value jar))
  59. (make-blocked
  60. (lambda (trans-id cleanup-proc wrap-proc)
  61. (clean-and-enqueue! (jar-queue jar)
  62. (make-q-item trans-id
  63. cleanup-proc
  64. wrap-proc)))))
  65. (else
  66. (let ((priority (jar-priority jar)))
  67. (set-jar-priority! jar (+ 1 priority))
  68. (make-enabled
  69. priority
  70. (lambda (queue)
  71. (let ((value (jar-value jar)))
  72. (set-jar-value! jar the-empty-jar-value)
  73. value)))))))))
  74. (define (jar-put! jar value)
  75. (if (not
  76. (with-new-proposal (lose)
  77. (cond
  78. ((not (empty-jar-value? (jar-value jar)))
  79. #f)
  80. ((clean-and-dequeue! (jar-queue jar))
  81. => (lambda (q-item)
  82. (let ((thread-queue (make-queue)))
  83. ((q-item-cleanup-proc q-item) thread-queue)
  84. (let ((trans-id (q-item-trans-id q-item)))
  85. (trans-id-set-value! trans-id
  86. (cons value
  87. (q-item-wrap-proc q-item)))
  88. (enqueue! thread-queue (trans-id-thread-cell trans-id))
  89. (or (maybe-commit-and-make-ready thread-queue)
  90. (lose))))))
  91. (else
  92. (set-jar-value! jar value)
  93. (or (maybe-commit)
  94. (lose))))))
  95. (assertion-violation 'jar-put! "jar is already full" jar value)))
  96. (define (jar-take jar)
  97. (sync (jar-take-rv jar)))