jar.scm 2.7 KB

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