1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
; Part of Scheme 48 1.9. See file COPYING for notices and license.
; Authors: Richard Kelsey, Jonathan Rees, Robert Ransom
; Higher-level proposal stuff.
; Execute THUNK atomically with its own proposal, saving and restoring
; the current proposal.
(define (call-atomically thunk)
(let ((old (current-proposal)))
(let loop ()
(set-current-proposal! (make-proposal))
(call-with-values thunk
(lambda results
(if (maybe-commit)
(begin
(set-current-proposal! old)
(apply values results))
(loop)))))))
; Ditto, but no values are returned.
(define (call-atomically! thunk)
(with-new-proposal (lose)
(thunk)
(or (maybe-commit)
(lose)))
(values))
; Same again, except that we use the current proposal, if there is one
; (and don't commit on the existing proposal).
(define (call-ensuring-atomicity thunk)
(if (current-proposal)
(thunk)
(call-atomically thunk)))
(define (call-ensuring-atomicity! thunk)
(if (current-proposal)
(thunk)
(call-atomically! thunk)))
; Macro versions of the above that avoid the need to write (lambda () ...)
; around the critical section.
(define-syntax atomically
(syntax-rules ()
((atomically)
(unspecific))
((atomically body ...)
(call-atomically
(lambda () body ...)))))
(define-syntax atomically!
(syntax-rules ()
((atomically)
(values))
((atomically body ...)
(call-atomically!
(lambda () body ...)))))
(define-syntax ensure-atomicity
(syntax-rules ()
((ensure-atomicity)
(unspecific))
((ensure-atomicity body ...)
(call-ensuring-atomicity
(lambda () body ...)))))
(define-syntax ensure-atomicity!
(syntax-rules ()
((ensure-atomicity)
(values))
((ensure-atomicity body ...)
(call-ensuring-atomicity!
(lambda () body ...)))))
; Save the existing proposal, install a new one, execute the body, and then
; replace the original proposal.
(define-syntax with-new-proposal
(syntax-rules ()
((with-new-proposal (?lose) ?body ?more ...)
(let ((old (current-proposal)))
(call-with-values
(lambda ()
(let ?lose ()
(set-current-proposal! (make-proposal))
(begin ?body ?more ...)))
(lambda results
(set-current-proposal! old)
(apply values results)))))))
; Useful for getting rid of a proposal before raising an error.
(define (remove-current-proposal!)
(set-current-proposal! #f))
; Useful for detecting that a proposal should be got rid of.
(define (proposal-active?)
(x->boolean (current-proposal)))
; For use when an inconsistency has been detected. The SET-CAR! ensures that
; the earlier PROVISIONAL-CAR will fail.
(define (invalidate-current-proposal!)
(let ((value (provisional-car j-random-pair)))
(set-car! j-random-pair (cons #f #f))
value))
(define j-random-pair (list #f))
|