mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-21 12:10:26 +02:00
SRFI-18 threads disjoint from guile threads
* doc/ref/srfi-modules.texi (SRFI-18 Threads): Update. * module/srfi/srfi-18.scm (<mutex>): Add owner field. (<thread>): New data type. (make-thread): Adapt for boxed threads. (thread-start!, thread-terminate!): Likewise. (mutex-state): Adapt for boxed threads. (mutex-lock!, mutex-unlock!): Update owner field.
This commit is contained in:
parent
bb4e955f0c
commit
3ce76c38cb
2 changed files with 78 additions and 67 deletions
|
@ -2085,6 +2085,9 @@ execution until @code{thread-start!} is called on it. Second, SRFI-18
|
||||||
threads are constructed with a top-level exception handler that
|
threads are constructed with a top-level exception handler that
|
||||||
captures any exceptions that are thrown on thread exit.
|
captures any exceptions that are thrown on thread exit.
|
||||||
|
|
||||||
|
SRFI-18 threads are disjoint from Guile's primitive threads.
|
||||||
|
@xref{Threads}, for more on Guile's primitive facility.
|
||||||
|
|
||||||
@defun current-thread
|
@defun current-thread
|
||||||
Returns the thread that called this function. This is the same
|
Returns the thread that called this function. This is the same
|
||||||
procedure as the same-named built-in procedure @code{current-thread}
|
procedure as the same-named built-in procedure @code{current-thread}
|
||||||
|
|
|
@ -80,10 +80,10 @@
|
||||||
terminated-thread-exception?
|
terminated-thread-exception?
|
||||||
uncaught-exception?
|
uncaught-exception?
|
||||||
uncaught-exception-reason)
|
uncaught-exception-reason)
|
||||||
#:re-export ((threads:current-thread . current-thread)
|
#:re-export ((srfi-34:raise . raise))
|
||||||
(threads:thread? . thread?)
|
|
||||||
(srfi-34:raise . raise))
|
|
||||||
#:replace (current-time
|
#:replace (current-time
|
||||||
|
current-thread
|
||||||
|
thread?
|
||||||
make-thread
|
make-thread
|
||||||
make-mutex
|
make-mutex
|
||||||
mutex?
|
mutex?
|
||||||
|
@ -112,11 +112,12 @@
|
||||||
(reason uncaught-exception-reason))
|
(reason uncaught-exception-reason))
|
||||||
|
|
||||||
(define-record-type <mutex>
|
(define-record-type <mutex>
|
||||||
(%make-mutex prim name specific)
|
(%make-mutex prim name specific owner)
|
||||||
mutex?
|
mutex?
|
||||||
(prim mutex-prim)
|
(prim mutex-prim)
|
||||||
(name mutex-name)
|
(name mutex-name)
|
||||||
(specific mutex-specific mutex-specific-set!))
|
(specific mutex-specific mutex-specific-set!)
|
||||||
|
(owner mutex-owner set-mutex-owner!))
|
||||||
|
|
||||||
(define-record-type <condition-variable>
|
(define-record-type <condition-variable>
|
||||||
(%make-condition-variable prim name specific)
|
(%make-condition-variable prim name specific)
|
||||||
|
@ -125,10 +126,16 @@
|
||||||
(name condition-variable-name)
|
(name condition-variable-name)
|
||||||
(specific condition-variable-specific condition-variable-specific-set!))
|
(specific condition-variable-specific condition-variable-specific-set!))
|
||||||
|
|
||||||
(define object-names (make-weak-key-hash-table))
|
(define-record-type <thread>
|
||||||
(define object-specifics (make-weak-key-hash-table))
|
(%make-thread prim name specific start-conds exception)
|
||||||
(define thread-start-conds (make-weak-key-hash-table))
|
thread?
|
||||||
(define thread->exception (make-object-property))
|
(prim thread-prim set-thread-prim!)
|
||||||
|
(name thread-name)
|
||||||
|
(specific thread-specific thread-specific-set!)
|
||||||
|
(start-conds thread-start-conds set-thread-start-conds!)
|
||||||
|
(exception thread-exception set-thread-exception!))
|
||||||
|
|
||||||
|
(define current-thread (make-parameter (%make-thread #f #f #f #f #f)))
|
||||||
(define thread-mutexes (make-parameter #f))
|
(define thread-mutexes (make-parameter #f))
|
||||||
|
|
||||||
;; EXCEPTIONS
|
;; EXCEPTIONS
|
||||||
|
@ -177,50 +184,37 @@
|
||||||
mutexes))))))
|
mutexes))))))
|
||||||
|
|
||||||
(define* (make-thread thunk #:optional name)
|
(define* (make-thread thunk #:optional name)
|
||||||
(let ((sm (make-mutex 'start-mutex))
|
(let* ((sm (make-mutex 'start-mutex))
|
||||||
(sc (make-condition-variable 'start-condition-variable)))
|
(sc (make-condition-variable 'start-condition-variable))
|
||||||
|
(thread (%make-thread #f name #f (cons sm sc) #f)))
|
||||||
(mutex-lock! sm)
|
(mutex-lock! sm)
|
||||||
(let ((t (threads:call-with-new-thread
|
(let ((prim (threads:call-with-new-thread
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(catch #t
|
(catch #t
|
||||||
(lambda ()
|
|
||||||
(with-thread-mutex-cleanup
|
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(mutex-lock! sm)
|
(parameterize ((current-thread thread))
|
||||||
(condition-variable-signal! sc)
|
(with-thread-mutex-cleanup
|
||||||
(mutex-unlock! sm sc)
|
(lambda ()
|
||||||
(thunk))))
|
(mutex-lock! sm)
|
||||||
(lambda (key . args)
|
(condition-variable-signal! sc)
|
||||||
(set! (thread->exception (threads:current-thread))
|
(mutex-unlock! sm sc)
|
||||||
(condition (&uncaught-exception
|
(thunk)))))
|
||||||
(reason
|
(lambda (key . args)
|
||||||
(match (cons key args)
|
(set-thread-exception!
|
||||||
(('srfi-34 obj) obj)
|
thread
|
||||||
(obj obj))))))))))))
|
(condition (&uncaught-exception
|
||||||
(when name (hashq-set! object-names t name))
|
(reason
|
||||||
|
(match (cons key args)
|
||||||
|
(('srfi-34 obj) obj)
|
||||||
|
(obj obj))))))))))))
|
||||||
|
(set-thread-prim! thread prim)
|
||||||
(mutex-unlock! sm sc)
|
(mutex-unlock! sm sc)
|
||||||
(hashq-set! thread-start-conds t (cons sm sc))
|
thread)))
|
||||||
t)))
|
|
||||||
|
|
||||||
(define (thread-name thread)
|
|
||||||
(hashq-ref object-names
|
|
||||||
(check-arg-type threads:thread? thread "thread-name")))
|
|
||||||
|
|
||||||
(define (thread-specific thread)
|
|
||||||
(hashq-ref object-specifics
|
|
||||||
(check-arg-type threads:thread? thread "thread-specific")))
|
|
||||||
|
|
||||||
(define (thread-specific-set! thread obj)
|
|
||||||
(hashq-set! object-specifics
|
|
||||||
(check-arg-type threads:thread? thread "thread-specific-set!")
|
|
||||||
obj)
|
|
||||||
*unspecified*)
|
|
||||||
|
|
||||||
(define (thread-start! thread)
|
(define (thread-start! thread)
|
||||||
(match (hashq-ref thread-start-conds
|
(match (thread-start-conds thread)
|
||||||
(check-arg-type threads:thread? thread "thread-start!"))
|
|
||||||
((smutex . scond)
|
((smutex . scond)
|
||||||
(hashq-remove! thread-start-conds thread)
|
(set-thread-start-conds! thread #f)
|
||||||
(mutex-lock! smutex)
|
(mutex-lock! smutex)
|
||||||
(condition-variable-signal! scond)
|
(condition-variable-signal! scond)
|
||||||
(mutex-unlock! smutex))
|
(mutex-unlock! smutex))
|
||||||
|
@ -267,27 +261,28 @@
|
||||||
;; A unique value.
|
;; A unique value.
|
||||||
(define %cancel-sentinel (list 'cancelled))
|
(define %cancel-sentinel (list 'cancelled))
|
||||||
(define (thread-terminate! thread)
|
(define (thread-terminate! thread)
|
||||||
(threads:cancel-thread thread %cancel-sentinel)
|
(threads:cancel-thread (thread-prim thread) %cancel-sentinel)
|
||||||
*unspecified*)
|
*unspecified*)
|
||||||
|
|
||||||
;; A unique value.
|
;; A unique value.
|
||||||
(define %timeout-sentinel (list 1))
|
(define %timeout-sentinel (list 1))
|
||||||
(define* (thread-join! thread #:optional (timeout %timeout-sentinel)
|
(define* (thread-join! thread #:optional (timeout %timeout-sentinel)
|
||||||
(timeoutval %timeout-sentinel))
|
(timeoutval %timeout-sentinel))
|
||||||
(with-exception-handlers-here
|
(let ((t (thread-prim thread)))
|
||||||
(lambda ()
|
(with-exception-handlers-here
|
||||||
(let ((v (if (eq? timeout %timeout-sentinel)
|
(lambda ()
|
||||||
(threads:join-thread thread)
|
(let* ((v (if (eq? timeout %timeout-sentinel)
|
||||||
(threads:join-thread thread timeout %timeout-sentinel))))
|
(threads:join-thread t)
|
||||||
(cond
|
(threads:join-thread t timeout %timeout-sentinel))))
|
||||||
((eq? v %timeout-sentinel)
|
(cond
|
||||||
(if (eq? timeoutval %timeout-sentinel)
|
((eq? v %timeout-sentinel)
|
||||||
(srfi-34:raise (condition (&join-timeout-exception)))
|
(if (eq? timeoutval %timeout-sentinel)
|
||||||
timeoutval))
|
(srfi-34:raise (condition (&join-timeout-exception)))
|
||||||
((eq? v %cancel-sentinel)
|
timeoutval))
|
||||||
(srfi-34:raise (condition (&terminated-thread-exception))))
|
((eq? v %cancel-sentinel)
|
||||||
((thread->exception thread) => srfi-34:raise)
|
(srfi-34:raise (condition (&terminated-thread-exception))))
|
||||||
(else v))))))
|
((thread-exception thread) => srfi-34:raise)
|
||||||
|
(else v)))))))
|
||||||
|
|
||||||
;; MUTEXES
|
;; MUTEXES
|
||||||
;; These functions are all pass-thrus to the existing Guile implementations.
|
;; These functions are all pass-thrus to the existing Guile implementations.
|
||||||
|
@ -297,38 +292,51 @@
|
||||||
'allow-external-unlock
|
'allow-external-unlock
|
||||||
'recursive)
|
'recursive)
|
||||||
name
|
name
|
||||||
|
#f
|
||||||
#f))
|
#f))
|
||||||
|
|
||||||
(define (mutex-state mutex)
|
(define (mutex-state mutex)
|
||||||
(let* ((prim (mutex-prim mutex))
|
(let* ((prim (mutex-prim mutex))
|
||||||
(owner (threads:mutex-owner prim)))
|
(owner (mutex-owner mutex)))
|
||||||
(if owner
|
(if owner
|
||||||
(if (threads:thread-exited? owner) 'abandoned owner)
|
(if (and=> (thread-prim owner) threads:thread-exited?)
|
||||||
|
'abandoned
|
||||||
|
owner)
|
||||||
(if (> (threads:mutex-level prim) 0) 'not-owned 'not-abandoned))))
|
(if (> (threads:mutex-level prim) 0) 'not-owned 'not-abandoned))))
|
||||||
|
|
||||||
(define (abandon-mutex! mutex)
|
(define (abandon-mutex! mutex)
|
||||||
#t)
|
#t)
|
||||||
|
|
||||||
(define (mutex-lock! mutex . args)
|
(define* (mutex-lock! mutex #:optional timeout (thread (current-thread)))
|
||||||
(let ((mutexes (thread-mutexes)))
|
(let ((mutexes (thread-mutexes)))
|
||||||
(when mutexes
|
(when mutexes
|
||||||
(hashq-set! mutexes mutex #t)))
|
(hashq-set! mutexes mutex #t)))
|
||||||
(with-exception-handlers-here
|
(with-exception-handlers-here
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(catch 'abandoned-mutex-error
|
(catch 'abandoned-mutex-error
|
||||||
(lambda () (apply threads:lock-mutex (mutex-prim mutex) args))
|
(lambda ()
|
||||||
|
(cond
|
||||||
|
((threads:lock-mutex (mutex-prim mutex) timeout)
|
||||||
|
(set-mutex-owner! mutex thread)
|
||||||
|
#t)
|
||||||
|
(else #f)))
|
||||||
(lambda (key . args)
|
(lambda (key . args)
|
||||||
|
(set-mutex-owner! mutex thread)
|
||||||
(srfi-34:raise
|
(srfi-34:raise
|
||||||
(condition (&abandoned-mutex-exception))))))))
|
(condition (&abandoned-mutex-exception))))))))
|
||||||
|
|
||||||
(define mutex-unlock!
|
(define mutex-unlock!
|
||||||
(case-lambda
|
(case-lambda
|
||||||
((mutex)
|
((mutex)
|
||||||
(threads:unlock-mutex (mutex-prim mutex)))
|
(set-mutex-owner! mutex #f)
|
||||||
|
(threads:unlock-mutex (mutex-prim mutex))
|
||||||
|
#t)
|
||||||
((mutex cond)
|
((mutex cond)
|
||||||
|
(set-mutex-owner! mutex #f)
|
||||||
(threads:unlock-mutex (mutex-prim mutex)
|
(threads:unlock-mutex (mutex-prim mutex)
|
||||||
(condition-variable-prim cond)))
|
(condition-variable-prim cond)))
|
||||||
((mutex cond timeout)
|
((mutex cond timeout)
|
||||||
|
(set-mutex-owner! mutex #f)
|
||||||
(threads:unlock-mutex (mutex-prim mutex)
|
(threads:unlock-mutex (mutex-prim mutex)
|
||||||
(condition-variable-prim cond)
|
(condition-variable-prim cond)
|
||||||
timeout))))
|
timeout))))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue