sunterlib/s48/cml/placeholder.scm

101 lines
2.6 KiB
Scheme
Raw Normal View History

; Placeholders (single-assignment cells for use with threads)
(define-record-type :placeholder
(really-make-placeholder priority queue value id)
placeholder?
(priority placeholder-priority set-placeholder-priority!)
(queue placeholder-queue set-placeholder-queue!)
(value placeholder-value-internal set-placeholder-value!)
(id placeholder-id))
(define-record-discloser :placeholder
(lambda (placeholder)
(cons 'placeholder
(if (placeholder-id placeholder)
(list (placeholder-id placeholder))
'()))))
(define-record-type :q-item
(make-q-item trans-id cleanup-thunk wrap-proc)
q-item?
(trans-id q-item-trans-id)
(cleanup-thunk q-item-cleanup-thunk)
(wrap-proc q-item-wrap-proc))
(define (clean-and-enqueue! queue value)
(clean-queue-head! queue)
(enqueue! queue value))
(define (clean-and-dequeue! queue)
(let loop ()
(if (queue-empty? queue)
#f
(let ((front (dequeue! queue)))
(if (trans-id-cancelled? (q-item-trans-id front))
(loop)
front)))))
(define (clean-queue-head! queue)
(let loop ()
(if (not (queue-empty? queue))
(let ((front (queue-front queue)))
(if (trans-id-cancelled? (q-item-trans-id front))
(begin
(dequeue! queue)
(loop)))))))
(define (make-placeholder . id-option)
(really-make-placeholder 0
(make-queue)
(unspecific)
(if (null? id-option)
#f
(car id-option))))
(define (placeholder-value-rv placeholder)
(make-base
(lambda ()
(cond
((placeholder-queue placeholder)
=> (lambda (queue)
(make-blocked
(lambda (trans-id cleanup-thunk wrap-proc)
(clean-and-enqueue! queue
(make-q-item trans-id
cleanup-thunk
wrap-proc))))))
(else
(let ((priority (placeholder-priority placeholder)))
(set-placeholder-priority! placeholder (+ 1 priority))
(make-enabled
priority
(lambda ()
(placeholder-value-internal placeholder)))))))))
(define (placeholder-set! placeholder value)
(enter-cr!)
(cond
((placeholder-queue placeholder)
=> (lambda (queue)
(set-placeholder-value! placeholder value)
(set-placeholder-queue! placeholder #f)
(let loop ()
(cond
((clean-and-dequeue! queue)
=> (lambda (q-item)
((q-item-cleanup-thunk q-item))
(cr-trans-id-wakeup (q-item-trans-id q-item)
(cons value
(q-item-wrap-proc q-item)))
(loop)))))
(leave-cr!)
(unspecific)))
(else
(leave-cr!)
(error "placeholder is already assigned" placeholder value))))
(define (placeholder-value placeholder)
(sync (placeholder-value-rv placeholder)))