bug#21887: 'monitor' form broken
It seems that the 'monitor' form is currently a no-op. The form (par-for-each (lambda (x) (monitor (foo))) xs) should be functionally equivalent to (let ((mutex (make-mutex))) (par-for-each (lambda (x) (with-mutex mutex (foo))) xs)) but currently becomes (par-for-each (lambda (x) (let ((mutex (make-mutex))) (with-mutex mutex (foo xs) which is ineffective. I don't know what's the best way to fix this. The simplest thing that comes to my mind is something along the lines of: (define-syntax monitor (lambda (stx) (syntax-case stx () ((_ body body* ...) (let ((uuid (generate-uuid))) #`(with-mutex (mutex-with-uuid #,uuid) body body* ...)) where mutex-with-uuid looks it up from a hash table at run-time and instantiates it when it doesn't exist, this operation also being synchronized across threads, like: (define mutex-table (make-hash-table)) (define mutex-table-mutex (make-mutex)) (define (mutex-with-uuid uuid) (with-mutex mutex-table-mutex (or (hash-ref mutex-table uuid) (let ((mutex (make-mutex))) (hash-set! mutex-table uuid mutex) mutex If that looks OK, I can try to make a proper patch from it. I'm not sure what I'd use in place of `generate-uuid' though. Would `gensym' be good enough? Shameless advertisement: with SRFI-126, the (or (hash-ref ...) ...) bit would have been just: (hashtable-intern! mutex-table uuid make-mutex) It's borrowed from MIT/GNU Scheme. Seems pretty useful. Taylan
bug#21894: escape continuation doc wrong about reinvokability
The manual says # Escape continuations are delimited continuations whose # only use is to make a non-local exit--i.e., to escape from the current # continuation. Such continuations are invoked only once, and for this # reason they are sometimes called "one-shot continuations". O RLY? scheme@(guile-user)> (use-modules (ice-9 control)) scheme@(guile-user)> (define cc #f) scheme@(guile-user)> (list 'a (let/ec e (list 'b (e (call-with-current-continuation (lambda (c) (set! cc c) 0)) $1 = (a 0) scheme@(guile-user)> (cc 1) $2 = (a 1) scheme@(guile-user)> (cc 2) $3 = (a 2) Clearly I have invoked this escape continuation, successfully, more than once. The semantics here are perfectly sensible, it's just the documentation that's off the mark, because it ignores how escape continuations interact with other kinds of continuation. I suggest changing "Such continuations are invoked only once" sentence to something like Such continuations can only be invoked from within the dynamic extent of the call to which they will jump. Because the jump ends that extent, if escape continuations are the only kind of continuations being used it is only possible to invoke an escape continuation at most once. For this reason they are sometimes called "one-shot continuations", but that is a misnomer when other kinds of continuations are also in use. Most kinds can reinstate a dynamic extent that has been exited, and if the extent of an escape continuation is reinstated then it can be invoked again to exit that extent again. Conversely, an escape continuation cannot be invoked from a separate thread that has its own dynamic state not including the continuation's extent, even if the continuation's extent is still in progress in its original thread and the continuation has never been invoked. -zefram
bug#21897: escape continuation passes barrier
scheme@(guile-user)> (use-modules (ice-9 control)) scheme@(guile-user)> (call/ec (lambda (c) (with-continuation-barrier (lambda () (c "through continuation"))) "c-w-b returned")) $1 = "through continuation" The continuation barrier works fine on call/cc continuations and on throw/catch, but doesn't block call/ec continuations. The manual doesn't mention any difference in behaviour for this case, nor can I see any obvious justification for it. The manual's statement that # Thus, `with-continuation-barrier' returns exactly once. is false in this case. I think a continuation barrier should block the use of the call/ec continuation. -zefram
bug#21899: let/ec continuations not distinct under compiler
With guile 2.0.11: scheme@(guile-user)> (use-modules (ice-9 control)) scheme@(guile-user)> (list 'a (let/ec ae (list 'b (let/ec be (be 2) $1 = (a (b 2)) scheme@(guile-user)> (list 'a (let/ec ae (list 'b (let/ec be (ae 2) $2 = (a (b 2)) scheme@(guile-user)> (list 'a (let/ec ae (list 'b (ae 2 $3 = (a 2) The middle of these three cases is wrong: it attempts to invoke the outer escape continuation, but only goes as far as the target of the inner one, which it isn't using. It therefore produces the same result as the first case, which invokes the inner escape continuation. It ought to behave like the third case, which shows that the outer escape continuation can be successfully invoked when the unused inner continuation is not present. The problem only affects let/ec, *not* call/ec: scheme@(guile-user)> (list 'a (call/ec (lambda (ae) (list 'b (call/ec (lambda (be) (be 2))) $4 = (a (b 2)) scheme@(guile-user)> (list 'a (call/ec (lambda (ae) (list 'b (call/ec (lambda (be) (ae 2))) $5 = (a 2) scheme@(guile-user)> (list 'a (call/ec (lambda (ae) (list 'b (ae 2) $6 = (a 2) It also only happens when compiling, not when interpreting: scheme@(guile-user)> ,o interp #t scheme@(guile-user)> (list 'a (let/ec ae (list 'b (let/ec be (be 2) $7 = (a (b 2)) scheme@(guile-user)> (list 'a (let/ec ae (list 'b (let/ec be (ae 2) $8 = (a 2) scheme@(guile-user)> (list 'a (let/ec ae (list 'b (ae 2 $9 = (a 2) -zefram