From: Matt Birkholz Date: Tue, 9 Aug 2016 17:59:01 +0000 (-0700) Subject: edwin/xterm.scm (get-xterm-input-operations): Eliminate busy loop. X-Git-Tag: mit-scheme-pucked-9.2.12~261^2~3 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=8658f6510fce9af234132318f2fc83ec0d056405;p=mit-scheme.git edwin/xterm.scm (get-xterm-input-operations): Eliminate busy loop. The busy loop in the keyboard peek-no-hang operation is more expensive than ever. Replace it with a timer in block-for-event. Cache current-thread and check that it has not changed before deregistering. --- diff --git a/src/edwin/xterm.scm b/src/edwin/xterm.scm index b744a293e..812cd8fdb 100644 --- a/src/edwin/xterm.scm +++ b/src/edwin/xterm.scm @@ -444,49 +444,41 @@ USA. update-screens! #f)))) (let ((get-next-event - (lambda (block?) - (let loop () - (let ((event (read-event queue display block?))) - (cond ((or (not event) (input-event? event)) - event) - ((not (vector? event)) - (let ((flag (process-change-event event))) - (if flag - (pce-event flag) - (loop)))) - (else - (or (process-event event) - (loop))))))))) + (lambda (msec) + (let ((timeout (and msec (+ (real-time-clock) msec)))) + (let loop () + (let ((event (read-event queue display timeout))) + (cond ((or (not event) (input-event? event)) + event) + ((not (vector? event)) + (let ((flag (process-change-event event))) + (if flag + (pce-event flag) + (loop)))) + (else + (or (process-event event) + (loop)))))))))) (let ((probe - (lambda (block?) - (let ((result (get-next-event block?))) + (lambda (msec) + (let ((result (get-next-event msec))) (if result (set! pending-result result)) - result))) - (guarantee-result - (lambda () - (or (get-next-event #t) - (error "#F returned from blocking read"))))) + result)))) (values (lambda () ;halt-update? (or pending-result (fix:< start end) - (probe 'IN-UPDATE))) - (lambda (timeout) ;peek-no-hang - (keyboard-peek-busy-no-hang - (lambda () - (or pending-result - (and (fix:< start end) - (string-ref string start)) - (probe #f))) - timeout)) + (probe 0))) + (lambda (msec) ;peek-no-hang + (or pending-result + (and (fix:< start end) + (string-ref string start)) + (probe msec))) (lambda () ;peek (or pending-result - (if (fix:< start end) - (string-ref string start) - (let ((result (guarantee-result))) - (set! pending-result result) - result)))) + (and (fix:< start end) + (string-ref string start)) + (probe #f))) (lambda () ;read (cond (pending-result => (lambda (result) @@ -497,26 +489,22 @@ USA. (set! start (fix:+ start 1)) char)) (else - (guarantee-result))))))))))) + (or (get-next-event #f) + (error "#F returned from blocking read")))))))))))) -(define (read-event queue display block?) - (let loop () - (let* ((empty "empty") - (event* (with-thread-events-blocked - (lambda () - (if (queue-empty? queue) - empty - (dequeue!/unsafe queue))))) - (event (if (eq? event* empty) - (and (not (memq block? '(IN-UPDATE #f))) - (block-for-event display)) - event*))) - (if (and event trace-port) - (write-line event trace-port)) - (or event - (if (memq block? '(IN-UPDATE #f)) - #f - (loop)))))) +(define (read-event queue display timeout) + (let* ((empty "empty") + (event* (with-thread-events-blocked + (lambda () + (if (queue-empty? queue) + empty + (dequeue!/unsafe queue))))) + (event (if (eq? event* empty) + (block-for-event display timeout) + event*))) + (if (and event trace-port) + (write-line event trace-port)) + event)) (define trace-port #f) @@ -544,22 +532,31 @@ USA. (vector-ref event 4) (vector-ref event 5)))) -(define (block-for-event display) +(define (block-for-event display timeout) display (let ((queue x-display-events) (output-available? #f) + (timed-out? #f) + (thread (current-thread)) + (timer) (registrations)) (let loop () ;; IO events are not delivered when input lingers in port buffers. ;; Incrementally drain the port before suspending. (set! output-available? (accept-process-output)) + (dynamic-wind (lambda () + (set! timer + (and timeout + (register-time-event timeout + (lambda () + (set! timed-out? #t))))) (set! registrations (if output-available? '() (register-process-output-events - (current-thread) + thread (lambda (mode) mode (set! output-available? #t)))))) @@ -578,17 +575,25 @@ USA. (if (and (queue-empty? queue) (not output-available?) + (not timed-out?) (not (process-status-changes?)) (not inferior-thread-changes?)) (suspend-current-thread))))) (lambda () - (for-each deregister-io-thread-event registrations) - (set! registrations))) + (if (eq? (current-thread) thread) + (begin + (if timer (deregister-time-event timer)) + (set! timer) + (for-each deregister-io-thread-event registrations) + (set! registrations))))) + (or (with-thread-events-blocked (lambda () (and (not (queue-empty? queue)) (dequeue!/unsafe queue)))) - (cond ((process-status-changes?) + (cond (timed-out? + #f) + ((process-status-changes?) event:process-status) (output-available? event:process-output)