placeholder.scm 2.9 KB

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