1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-09 21:40:33 +02:00

srfi-18: When timeout is a number, it's a relative number of seconds.

Fixes <https://bugs.gnu.org/29704>.
Reported by David Beswick <dlbeswick@gmail.com>.

* module/srfi/srfi-18.scm (timeout->absolute-time): New procedure.
(mutex-lock!): Use it in 'thread:lock-mutex' call.
(mutex-unlock!): Use it.
* test-suite/tests/srfi-18.test ("mutex-lock! returns false on timeout")
("mutex-lock! returns true when lock obtained within timeout")
("recursive lock waits")
("mutex unlock is false when condition times out"): Adjust cases where
the 'timeout' parameter is a number so that it's a relative number.
This commit is contained in:
Ludovic Courtès 2018-02-16 15:14:09 +01:00 committed by Andy Wingo
parent 4024a5beb3
commit cac14ad34d
2 changed files with 33 additions and 24 deletions

View file

@ -1,6 +1,6 @@
;;; srfi-18.scm --- Multithreading support ;;; srfi-18.scm --- Multithreading support
;; Copyright (C) 2008, 2009, 2010, 2012, 2014 Free Software Foundation, Inc. ;; Copyright (C) 2008, 2009, 2010, 2012, 2014, 2018 Free Software Foundation, Inc.
;; ;;
;; This library is free software; you can redistribute it and/or ;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public ;; modify it under the terms of the GNU Lesser General Public
@ -139,6 +139,16 @@
(define current-thread (make-parameter (%make-thread #f #f #f #f #f))) (define current-thread (make-parameter (%make-thread #f #f #f #f #f)))
(define thread-mutexes (make-parameter #f)) (define thread-mutexes (make-parameter #f))
(define (timeout->absolute-time timeout)
"Return an absolute time in seconds corresponding to TIMEOUT. TIMEOUT
can be any value authorized by SRFI-18: a number (relative time), a time
object (absolute point in time), or #f."
(cond ((number? timeout) ;seconds relative to now
(+ ((@ (guile) current-time)) timeout))
((time? timeout) ;absolute point in time
(time->seconds timeout))
(else timeout))) ;pair or #f
;; EXCEPTIONS ;; EXCEPTIONS
;; All threads created by SRFI-18 have an initial handler installed that ;; All threads created by SRFI-18 have an initial handler installed that
@ -308,7 +318,8 @@
(with-exception-handlers-here (with-exception-handlers-here
(lambda () (lambda ()
(cond (cond
((threads:lock-mutex (mutex-prim mutex) timeout) ((threads:lock-mutex (mutex-prim mutex)
(timeout->absolute-time timeout))
(set-mutex-owner! mutex thread) (set-mutex-owner! mutex thread)
(when (mutex-abandoned? mutex) (when (mutex-abandoned? mutex)
(set-mutex-abandoned?! mutex #f) (set-mutex-abandoned?! mutex #f)
@ -320,20 +331,21 @@
(define %unlock-sentinel (list 'unlock)) (define %unlock-sentinel (list 'unlock))
(define* (mutex-unlock! mutex #:optional (cond-var %unlock-sentinel) (define* (mutex-unlock! mutex #:optional (cond-var %unlock-sentinel)
(timeout %unlock-sentinel)) (timeout %unlock-sentinel))
(when (mutex-owner mutex) (let ((timeout (timeout->absolute-time timeout)))
(set-mutex-owner! mutex #f) (when (mutex-owner mutex)
(cond (set-mutex-owner! mutex #f)
((eq? cond-var %unlock-sentinel) (cond
(threads:unlock-mutex (mutex-prim mutex))) ((eq? cond-var %unlock-sentinel)
((eq? timeout %unlock-sentinel) (threads:unlock-mutex (mutex-prim mutex)))
(threads:wait-condition-variable (condition-variable-prim cond-var) ((eq? timeout %unlock-sentinel)
(mutex-prim mutex)) (threads:wait-condition-variable (condition-variable-prim cond-var)
(threads:unlock-mutex (mutex-prim mutex))) (mutex-prim mutex))
((threads:wait-condition-variable (condition-variable-prim cond-var) (threads:unlock-mutex (mutex-prim mutex)))
(mutex-prim mutex) ((threads:wait-condition-variable (condition-variable-prim cond-var)
timeout) (mutex-prim mutex)
(threads:unlock-mutex (mutex-prim mutex))) timeout)
(else #f)))) (threads:unlock-mutex (mutex-prim mutex)))
(else #f)))))
;; CONDITION VARIABLES ;; CONDITION VARIABLES
;; These functions are all pass-thrus to the existing Guile implementations. ;; These functions are all pass-thrus to the existing Guile implementations.

View file

@ -1,7 +1,7 @@
;;;; srfi-18.test --- Test suite for Guile's SRFI-18 functions. -*- scheme -*- ;;;; srfi-18.test --- Test suite for Guile's SRFI-18 functions. -*- scheme -*-
;;;; Julian Graham, 2007-10-26 ;;;; Julian Graham, 2007-10-26
;;;; ;;;;
;;;; Copyright (C) 2007, 2008, 2012 Free Software Foundation, Inc. ;;;; Copyright (C) 2007, 2008, 2012, 2018 Free Software Foundation, Inc.
;;;; ;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
@ -233,7 +233,7 @@
(pass-if "mutex-lock! returns false on timeout" (pass-if "mutex-lock! returns false on timeout"
(let* ((m (make-mutex 'mutex-lock-2)) (let* ((m (make-mutex 'mutex-lock-2))
(t (make-thread (lambda () (mutex-lock! m (current-time) #f))))) (t (make-thread (lambda () (mutex-lock! m 0 #f)))))
(mutex-lock! m) (mutex-lock! m)
(thread-start! t) (thread-start! t)
(not (thread-join! t)))) (not (thread-join! t))))
@ -241,9 +241,7 @@
(pass-if "mutex-lock! returns true when lock obtained within timeout" (pass-if "mutex-lock! returns true when lock obtained within timeout"
(let* ((m (make-mutex 'mutex-lock-3)) (let* ((m (make-mutex 'mutex-lock-3))
(t (make-thread (lambda () (t (make-thread (lambda ()
(mutex-lock! m (+ (time->seconds (current-time)) (mutex-lock! m 100 #f)))))
100)
#f)))))
(mutex-lock! m) (mutex-lock! m)
(thread-start! t) (thread-start! t)
(mutex-unlock! m) (mutex-unlock! m)
@ -306,8 +304,7 @@
(let* ((m (make-mutex 'mutex-unlock-2)) (let* ((m (make-mutex 'mutex-unlock-2))
(t (make-thread (lambda () (t (make-thread (lambda ()
(mutex-lock! m) (mutex-lock! m)
(let ((now (time->seconds (current-time)))) (mutex-lock! m 0.1)
(mutex-lock! m (+ now 0.1)))
(mutex-unlock! m)) (mutex-unlock! m))
'mutex-unlock-2))) 'mutex-unlock-2)))
(thread-start! t) (thread-start! t)
@ -352,7 +349,7 @@
(let* ((m (make-mutex 'mutex-unlock-4)) (let* ((m (make-mutex 'mutex-unlock-4))
(c (make-condition-variable 'mutex-unlock-4))) (c (make-condition-variable 'mutex-unlock-4)))
(mutex-lock! m) (mutex-lock! m)
(not (mutex-unlock! m c (+ (time->seconds (current-time)) 1)))))) (not (mutex-unlock! m c 1)))))
(with-test-prefix "condition-variable?" (with-test-prefix "condition-variable?"