In http://arclanguage.org/item?id=2740 I published a fix for the bug that atomic stops being atomic if an error is thrown in its thunk. In that patch I had the ar-sema-cell flag being set in the "before" part of dynamic-wind. While I don't think that the "before" part would ever be executed more than once because full continuation jumps are blocked across the call-with-semaphore call, I do think it was confusing because normally the "before" part of a dynamic-wind would be executed whenever a continuation captured in the "middle" part was reentered. Thus I thought the code would be clearer if we used a mechanism similar to "protect", where it's clear that we're catching any kind of exit from the "middle" thunk but we've not trying to catch entering the thunk multiple times. And of course to "use a mechanism similar to protect", we can simply use protect: (define (protect during after)
(dynamic-wind (lambda () #t) during after))
(xdef 'protect protect)
(xdef 'atomic-invoke (lambda (f)
(if (thread-cell-ref ar-sema-cell)
(ar-apply f '())
(begin
(thread-cell-set! ar-sema-cell #t)
(protect
(lambda ()
(call-with-semaphore
ar-the-sema
(lambda () (ar-apply f '()))))
(lambda ()
(thread-cell-set! ar-sema-cell #f)))))))
A patch file against arc2 for this change is available at http://catdancer.ws/arc/arc2-atomic.patch |