From 36155e913e9f9ab94667e0c4e0abc8038ffda0a6 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 17 Jan 2011 09:21:50 -0700 Subject: [PATCH] get rid of the old barriers around GUI event dispatch since, on further reflection, it doesn't seem needed, and a simple prompt seems to make everything work right --- collects/mred/private/wx/common/queue.rkt | 40 +++----- collects/scribblings/gui/win-overview.scrbl | 97 ++++--------------- doc/release-notes/racket/Draw_and_GUI_5_1.txt | 4 +- 3 files changed, 39 insertions(+), 102 deletions(-) diff --git a/collects/mred/private/wx/common/queue.rkt b/collects/mred/private/wx/common/queue.rkt index 460c8a79a9..1ed6ed3f5c 100644 --- a/collects/mred/private/wx/common/queue.rkt +++ b/collects/mred/private/wx/common/queue.rkt @@ -390,31 +390,21 @@ (define event-dispatch-handler (make-parameter really-dispatch-event)) (define (handle-event thunk e) - (let/ec esc ; used to disable continuation aborts/jumps past here - (let ([done? #f]) - (dynamic-wind - void - (lambda () - (call-with-continuation-barrier - (lambda () - (call-with-continuation-prompt ; to delimit continuations - (lambda () - (call-with-continuation-prompt ; to delimit search for dispatch-event-key - (lambda () - ;; communicate the thunk to `really-dispatch-event': - (let ([b (box thunk)]) - ;; use the event-dispatch handler: - (with-continuation-mark dispatch-event-key b - ((event-dispatch-handler) e)) - ;; if the event-dispatch handler doesn't chain - ;; to the original one, then do so now: - (when (unbox b) - (set-box! b #f) - (thunk)))) - dispatch-event-prompt))))) - (set! done? #t)) - (lambda () - (unless done? (esc (void)))))))) + (call-with-continuation-prompt ; to delimit continuations + (lambda () + (call-with-continuation-prompt ; to delimit search for dispatch-event-key + (lambda () + ;; communicate the thunk to `really-dispatch-event': + (let ([b (box thunk)]) + ;; use the event-dispatch handler: + (with-continuation-mark dispatch-event-key b + ((event-dispatch-handler) e)) + ;; if the event-dispatch handler doesn't chain + ;; to the original one, then do so now: + (when (unbox b) + (set-box! b #f) + (thunk)))) + dispatch-event-prompt)))) (define yield (case-lambda diff --git a/collects/scribblings/gui/win-overview.scrbl b/collects/scribblings/gui/win-overview.scrbl index 9fc65796b3..a7b9d44df4 100644 --- a/collects/scribblings/gui/win-overview.scrbl +++ b/collects/scribblings/gui/win-overview.scrbl @@ -923,86 +923,31 @@ An eventspace is a @techlink[#:doc reference-doc]{synchronizable parent. (Note that the blocking state of an eventspace is unrelated to whether an event is ready for dispatching.) -@subsection[#:tag "evtcontjump"]{Exceptions, Continuations, and Jumps} +@subsection[#:tag "evtcontjump"]{Continuations and Event Dispatch} Whenever the system dispatches an event, the call to the handler is - wrapped with a @deftech{continuation prompt} that delimits - continuations captured by the handler (see - @racket[call-with-continuation-prompt]). For example, if a button - callback captures a continuation, then applying the continuation - later reinstalls only the work to be done by the handler up until the - point that it returns; the dispatch machinery to invoke the button - callback is not included in the continuation. The delimited - continuation prompt is installed outside the call to the @tech{event - dispatch handler}, so any captured continuation includes the - invocation of the @tech{event dispatch handler}. + wrapped with a @deftech{continuation prompt} (see + @racket[call-with-continuation-prompt]) that delimits continuation + aborts (such as when an exception is raised) and continuations + captured by the handler. The delimited continuation prompt is + installed outside the call to the @tech{event dispatch handler}, so + any captured continuation includes the invocation of the @tech{event + dispatch handler}. -An event-handling callback (and the @tech{event dispatch handler}) is - further wrapped with a @deftech{continuation barrier} and a - @racket[dynamic-wind] that blocks jumps (using continuation prompts - other than the default one) that escape past the dispatch site. The - following @scheme[block] procedure illustrates how the system blocks - escape continuation jumps: - -@def+int[ -(define (block f) - (code:comment @#,t{calls @scheme[f] and returns void if @scheme[f] tries to escape}) - (let ([done? #f]) - (let/ec k - (dynamic-wind - void - (lambda () (begin0 (f) (set! done? #t))) - (lambda () (unless done? (k (void)))))))) - -(block (lambda () 5)) -(let/ec k (block (lambda () (k 10)))) -(let/ec k ((lambda () (k 10))) 11) -(let/ec k (block (lambda () (k 10))) 11) -] - -This blocking of continuation jumps complicates the interaction - between @scheme[with-handlers] and @scheme[yield] (or the default - @tech{event dispatch handler}). For example, in evaluating the expression - -@schemeblock[ -(with-handlers ([(lambda (x) #t) - (lambda (x) (error "error during yield"))]) - (yield)) -] - -the @scheme["error during yield"] handler is @italic{never} called, - even if a callback procedure invoked by @scheme[yield] raises an - exception. The @scheme[with-handlers] expression installs an - exception handler that tries to jump back to the context of the - @scheme[with-handlers] expression before invoking a handler - procedure; this jump is blocked by the dispatch within - @scheme[yield], so @scheme["error during yield"] is never - printed. Exceptions during @scheme[yield] are ``handled'' in the - sense that control jumps out of the event handler, but @scheme[yield] - may dispatch another event rather than escaping or returning. - -The following expression demonstrates a more effective way to handle - exceptions within @scheme[yield], for the rare cases where such - handling is useful: - -@schemeblock[ -(let/ec k - (call-with-exception-handler - (lambda (x) - (error "error during yield") - (k)) - (lambda () - (yield)))) -] - -This expression installs an exception handler that prints an error - message @italic{before} trying to escape. Like the continuation escape - associated with @scheme[with-handlers], the escape to @scheme[k] never - succeeds. Nevertheless, if an exception is raised by an event - handler during the call to @scheme[yield], an error message is - printed before control returns to the event dispatcher within - @scheme[yield]. +For example, if a button callback raises an exception, than the abort + performed by the default exception handler returns to the event-dispatch + point, rather than terminating the program or escaping past an enclosing + @racket[(yield)]. If @racket[with-handlers] wraps a @racket[(yield)] that + leads to an exception raised by a button callback, however, the exception + can be captured by the @racket[with-handlers]. +Along similar lines, if a button callback captures a continuation + (using the default continuation prompt tag), then applying the + continuation re-installs only the work to be done by the handler up + until the point that it returns; the dispatch machinery to invoke the + button callback is not included in the continuation. A continuation + captured during a button callback is therefore potentially useful + outside of the same callback. @section[#:tag "animation"]{Animation in Canvases} diff --git a/doc/release-notes/racket/Draw_and_GUI_5_1.txt b/doc/release-notes/racket/Draw_and_GUI_5_1.txt index e45603c67f..d44cc4d9ab 100644 --- a/doc/release-notes/racket/Draw_and_GUI_5_1.txt +++ b/doc/release-notes/racket/Draw_and_GUI_5_1.txt @@ -151,7 +151,9 @@ into the control. Event callbacks are delimited by a continuation prompt using the default continuation prompt tag. As a result, continuations can be usufully captured during one event callback and applied during other -callbacks or outside of an even callback. +callbacks or outside of an even callback. The continuation barrier and +jump-defeating `dynamic-wind' that formerly guarded callbacks has been +removed. Removed Functions