placeholder.scm 3.0 KB

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