[previous] [up] [next]     [index]
Next: Mouse and Keyboard Events Up: Event Dispatching and Eventspaces Previous: Creating and Setting the

Exceptions and Continuation Jumps

Whenever the system dispatches an event, the call to the handler procedure is wrapped so that full continuation jumps are not allowed to escape from the dispatch, and escape continuation jumps are blocked at the dispatch site. The following block procedure illustrates how the system blocks escape continuation jumps:

  (define (block f)
    ; calls f, returning (void) if 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)) ; => 5 (let/ec k (block (lambda () (k 10)))) ; => void (let/ec k ((lambda () (k 10))) 11) ; => 10 (let/ec k (block (lambda () (k 10))) 11) ; => 11

Calls to the event dispatch handler are also protected with block.

This blocking of continuation jumps complicates the interaction between with-handlers and yield (or the default event dispatch handler). For example, in evaluating the expression

  (with-handlers ([(lambda (x) #t)
                   (lambda (x) (error "error during yield"))])
    (yield)) 
the "error during yield" handler is never called, even if a callback procedure invoked by yield raises an exception. The with-handlers expression installs an exception handler that tries to jump back to the context of the with-handlers expression before invoking a handler procedure; this jump is blocked by the dispatch within yield, so "error during yield" is never printed. Exceptions during yield are ``handled'' in the sense that control jumps out of the event handler, but yield may dispatch another event rather than escaping or returning.

The following expression demonstrates a more useful way to handle exceptions within yield:

  (let/ec k
    (parameterize ([current-exception-handler
                    (lambda (x)
                      (error "error during yield")
                      (k))])
      (yield))) 
This expression installs an exception handler that prints an error message before trying to escape. Like the continuation escape associated with with-handlers, the escape to k never succeeds. Nevertheless, if an exception is raised by an event handler during the call to yield, an error message is printed before control returns to the event dispatcher within yield.


[previous] [up] [next]     [index]
Next: Mouse and Keyboard Events Up: Event Dispatching and Eventspaces Previous: Creating and Setting the

PLT