bug#21887: 'monitor' form broken

2015-11-12 Thread Taylan Ulrich Bayırlı/Kammer
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

2015-11-12 Thread Zefram
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

2015-11-12 Thread Zefram
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

2015-11-12 Thread Zefram
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