diff options
author | Clément Lassieur <clement@lassieur.org> | 2018-08-05 21:10:07 +0200 |
---|---|---|
committer | Clément Lassieur <clement@lassieur.org> | 2018-08-16 19:19:23 +0200 |
commit | e66e545b69c3adfba6fd1adb0f018f85ceed495f (patch) | |
tree | 14d85b55d5c8b574dd5bf1c79ca7e12186e4f561 | |
parent | 4db99f647b3677086a2007763726d05a59b0cdcb (diff) | |
download | cuirass-e66e545b69c3adfba6fd1adb0f018f85ceed495f.tar cuirass-e66e545b69c3adfba6fd1adb0f018f85ceed495f.tar.gz |
utils: Avoid deadlock when WITH-CRITICAL-SECTION calls are nested.
* src/cuirass/utils.scm (%critical-section-args): New parameter.
(make-critical-section): Put ARGS into a parameter, so that
CALL-WITH-CRITICAL-SECTION knows when it's called from the critical section.
In that case it would just apply PROC to ARGS.
(call-with-critical-section): If already in the critical section, apply PROC
to %CRITICAL-SECTION-ARGS instead of sending the message through the critical
section channel.
-rw-r--r-- | src/cuirass/utils.scm | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/src/cuirass/utils.scm b/src/cuirass/utils.scm index 9e9ac36..6083890 100644 --- a/src/cuirass/utils.scm +++ b/src/cuirass/utils.scm @@ -94,6 +94,9 @@ delimited continuations and fibers." (conclusion) (apply throw args))))) +(define %critical-section-args + (make-parameter #f)) + (define (make-critical-section . args) "Return a channel used to implement a critical section. That channel can then be passed to 'join-critical-section', which will ensure sequential @@ -104,19 +107,23 @@ dedicated fiber." (let ((channel (make-channel))) (spawn-fiber (lambda () - (let loop () - (match (get-message channel) - (((? channel? reply) . (? procedure? proc)) - (put-message reply (apply proc args)))) - (loop)))) + (parameterize ((%critical-section-args args)) + (let loop () + (match (get-message channel) + (((? channel? reply) . (? procedure? proc)) + (put-message reply (apply proc args)))) + (loop))))) channel)) (define (call-with-critical-section channel proc) - "Call PROC in the critical section corresponding to CHANNEL. Return the -result of PROC." - (let ((reply (make-channel))) - (put-message channel (cons reply proc)) - (get-message reply))) + "Send PROC to the critical section through CHANNEL. Return the result of +PROC. If already in the critical section, call PROC immediately." + (let ((args (%critical-section-args))) + (if args + (apply proc args) + (let ((reply (make-channel))) + (put-message channel (cons reply proc)) + (get-message reply))))) (define-syntax-rule (with-critical-section channel (vars ...) exp ...) "Evaluate EXP... in the critical section corresponding to CHANNEL. |