1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

srfi-18: Avoid call/cc.

* module/srfi/srfi-18.scm (with-exception-handlers-here): New function.
  (wrap): Remove.
  (thread-join!, mutex-lock!): Use with-exception-handlers-here instead
  of the call/cc+wrap mess.
This commit is contained in:
Andy Wingo 2016-10-31 20:52:08 +01:00
parent c3f08aa866
commit 789a4d8d87

View file

@ -220,18 +220,26 @@
(when (> usecs 0) (usleep usecs)) (when (> usecs 0) (usleep usecs))
*unspecified*)) *unspecified*))
;; A convenience function for installing exception handlers on SRFI-18 ;; Whereas SRFI-34 leaves the continuation of a call to an exception
;; primitives that resume the calling continuation after the handler is ;; handler unspecified, SRFI-18 has this to say:
;; invoked -- this resolves a behavioral incompatibility with Guile's ;;
;; implementation of SRFI-34, which uses lazy-catch and rethrows handled ;; When one of the primitives defined in this SRFI raises an exception
;; exceptions. (SRFI-18, "Primitives and exceptions") ;; defined in this SRFI, the exception handler is called with the same
;; continuation as the primitive (i.e. it is a tail call to the
;; exception handler).
;;
;; Therefore arrange for exceptions thrown by SRFI-18 primitives to run
;; handlers with the continuation of the primitive call, for those
;; primitives that throw exceptions.
(define (wrap thunk) (define (with-exception-handlers-here thunk)
(lambda (continuation) (let ((tag (make-prompt-tag)))
(with-exception-handler (lambda (obj) (call-with-prompt tag
((current-exception-handler) obj) (lambda ()
(continuation)) (with-exception-handler (lambda (exn) (abort-to-prompt tag exn))
thunk))) thunk))
(lambda (k exn)
((current-exception-handler) exn)))))
;; A pass-thru to cancel-thread that first installs a handler that throws ;; A pass-thru to cancel-thread that first installs a handler that throws
;; terminated-thread exception, as per SRFI-18, ;; terminated-thread exception, as per SRFI-18,
@ -253,15 +261,14 @@
*unspecified*)) *unspecified*))
(define (thread-join! thread . args) (define (thread-join! thread . args)
(define thread-join-inner! (with-exception-handlers-here
(wrap (lambda () (lambda ()
(let ((v (apply threads:join-thread thread args)) (let ((v (apply threads:join-thread thread args))
(e (thread->exception thread))) (e (thread->exception thread)))
(if (and (= (length args) 1) (not v)) (if (and (= (length args) 1) (not v))
(srfi-34:raise (condition (&join-timeout-exception)))) (srfi-34:raise (condition (&join-timeout-exception))))
(if e (srfi-34:raise e)) (if e (srfi-34:raise e))
v)))) v))))
(call/cc thread-join-inner!))
;; MUTEXES ;; MUTEXES
;; These functions are all pass-thrus to the existing Guile implementations. ;; These functions are all pass-thrus to the existing Guile implementations.
@ -293,14 +300,13 @@
(if (> (threads:mutex-level mutex) 0) 'not-owned 'not-abandoned)))) (if (> (threads:mutex-level mutex) 0) 'not-owned 'not-abandoned))))
(define (mutex-lock! mutex . args) (define (mutex-lock! mutex . args)
(define mutex-lock-inner! (with-exception-handlers-here
(wrap (lambda () (lambda ()
(catch 'abandoned-mutex-error (catch 'abandoned-mutex-error
(lambda () (apply threads:lock-mutex mutex args)) (lambda () (apply threads:lock-mutex mutex args))
(lambda (key . args) (lambda (key . args)
(srfi-34:raise (srfi-34:raise
(condition (&abandoned-mutex-exception)))))))) (condition (&abandoned-mutex-exception))))))))
(call/cc mutex-lock-inner!))
(define (mutex-unlock! mutex . args) (define (mutex-unlock! mutex . args)
(apply threads:unlock-mutex mutex args)) (apply threads:unlock-mutex mutex args))