repair uninterrupted-exit on continuation application

This commit is contained in:
Matthew Flatt 2018-07-29 06:42:03 -06:00
parent d0f73f5ea8
commit e066bb44ea
2 changed files with 47 additions and 74 deletions

View File

@ -1464,8 +1464,8 @@
(run #t))
;; Make sure that transitive thread-resume keeps a weak link
;; when thread is blocked (but only test under 3m):
(when (regexp-match #rx"3m" (path->bytes (system-library-subpath)))
;; when thread is blocked
(unless (eq? 'cgc (system-type 'gc))
(let ([run
(lambda (suspend-first?)
(let ([done (make-semaphore)])

View File

@ -194,13 +194,8 @@
#f ; not a tail call
(lambda ()
(end-uninterrupted 'prompt)
;; Make room for a slicing continuation-mark frame, in case this
;; metacontinuation frame is capture and composed in a context
;; that already has marks:
(call-with-splice-k
(lambda ()
;; Finally, apply the given function:
(apply proc args)))))]))
(apply proc args)))]))
(define (make-default-abort-handler tag)
(lambda (abort-thunk)
@ -409,9 +404,7 @@
(check who (procedure-arity-includes/c 1) proc)
(check who continuation-prompt-tag? tag)
(maybe-future-barricade tag)
(call-with-end-uninterrupted
(lambda ()
(call/cc
(call/cc/end-uninterrupted
(lambda (k)
(|#%app|
proc
@ -421,7 +414,7 @@
(current-mark-stack)
(current-mark-splice)
(extract-metacontinuation 'call-with-current-continuation (strip-impersonator tag) #t)
tag))))))]))
tag))))]))
(define/who call-with-composable-continuation
(case-lambda
@ -433,9 +426,7 @@
(call-with-composable-continuation* p tag #t)]))
(define (call-with-composable-continuation* p tag wind?)
(call-with-end-uninterrupted
(lambda ()
(call/cc
(call/cc/end-uninterrupted
(lambda (k)
(|#%app|
p
@ -446,7 +437,7 @@
(current-winders)
(current-mark-stack)
(current-mark-splice)
(extract-metacontinuation 'call-with-composable-continuation (strip-impersonator tag) #f))))))))
(extract-metacontinuation 'call-with-composable-continuation (strip-impersonator tag) #f))))))
(define (unsafe-call-with-composable-continuation/no-wind p tag)
(call-with-composable-continuation* p tag #f))
@ -541,7 +532,7 @@
;; the metacontinuation won't change (except by escaping):
(activate-and-wrap-cc-guard-for-impersonator!
(non-composable-continuation-tag c)))
(apply (full-continuation-k c) args))
((full-continuation-k c) (lambda () (end-uninterrupted-with-values args))))
;; If a winder changed the meta-continuation, try again for a
;; non-composable continuation:
(and (non-composable-continuation? c)
@ -555,7 +546,7 @@
(current-metacontinuation)))
(current-winders (full-continuation-winders c))
(current-mark-splice (full-continuation-mark-splice c))
(apply (full-continuation-k c) args))
((full-continuation-k c) (lambda () (end-uninterrupted-with-values args))))
;; Used as a "handler" for a prompt without a tag, which is used for
;; composable continuations
@ -628,14 +619,6 @@
(raise-continuation-error '|continuation application|
"attempt to cross a continuation barrier"))
;; Update `empty-k` for splicing to be the "inside" of a continuation prompt.
(define (call-with-splice-k thunk)
(call-with-end-uninterrupted
(lambda ()
(call-setting-continuation-attachment
'empty
(lambda () (thunk))))))
(define (set-continuation-applicables!)
(let ([add (lambda (rtd)
(struct-property-set! prop:procedure
@ -891,34 +874,24 @@
(lambda ()
body))))]))
;; Ensure that we have an `(end-uninterrupted)` in the immediate
;; continuation, but keep the illusion that `thunk` is called in
;; tail position.
(define (call-with-end-uninterrupted thunk)
(call-with-current-continuation-attachment
empty-mark-frame
(lambda (a)
(cond
[(or (eq? a 'empty)
(and (mark-frame? a)
(mark-frame-end-uninterupted? a)))
;; an end-uninterupted check is in place
(thunk)]
[else
;; Add an uninteruped check, moving the current continuation
;; marks to the more nested continuation
(call-setting-continuation-attachment
'skip
(lambda ()
(call/cc
;; Return a continuation that expects a thunk to resume. That way, we
;; can can an `(end-uninterrupted)` and check for breaks in the
;; destination continuation
(define (call/cc/end-uninterrupted proc)
((call/cc
(lambda (k)
(call-setting-continuation-attachment
(let ([a (coerce-to-mark-frame a)])
(make-mark-frame (mark-frame-table a)
#f
(mark-frame-flat a)))
(lambda ()
(thunk)))))))]))))
(proc k))))))
;; Called on the arguments to return to a continuation
;; captured by `call/cc/end-uninterrupted`:
(define (end-uninterrupted-with-values args)
;; Arguably, we should use `end-uninterrupted/hook` here to check
;; for breaks, in case a jump enabled breaks and one is pending.
;; The traditional Racket implementation doesn't include that
;; check, and the check imposes a costs, so we leave it out for now.
(end-uninterrupted 'cc)
(apply values args))
(define (current-mark-chain)
(get-current-mark-chain (current-mark-stack) (current-mark-splice) (current-metacontinuation)))