Is there any way for dynamic-wind to know about the context of the continuation being jumped to in order to skip doing useless work?
To explain I mean and why I want such a thing, I have written some code that uses semaphores as mutexes, and most of my code acquires the mutex using call-with-semaphore. However, some functions need to do slightly more than what call-with-semaphore allows, because a sub-computation may also temporarily release the mutex, then re-acquire it when the sub-computation returns. To make that more concrete, here’s some code that does just that, using a call-with-semaphore/release function that I’ve written: (call-with-semaphore/release mutex (lambda (call-with-released) (do-something-with-the-mutex-locked!) (call-with-released (lambda () (do-something-with-the-mutex-unlocked!))) (do-some-more-with-the-mutex-locked!))) The call-with-semaphore procedure provided by racket/base installs a continuation barrier on every call, but I would like to be able to capture a continuation inside the inner portion, within the call-with-released thunk, so I’ve implemented call-with-semaphore/release using two uses of dynamic-wind: one to lock the mutex on entrance and unlock it on exit, and another to do precisely the inverse for around the code for which the mutex is released. The problem with that is if I have code like (call-with-semaphore/release mutex (lambda (call-with-released) (call-with-released (lambda () (call/cc (lambda (k) (stash-continuation-and-abort! k))))))) then when the continuation k is invoked from outside the dynamic extent of the call-with-semaphore/release application, the continuation will not start executing until it can acquire the mutex, even though it will release the mutex as soon as it acquires it. This is very wasteful, since it creates a lot of unnecessary contention for the mutex. I guess one way I could avoid this would be to make every call to call-with-semaphore/release install a fresh prompt, then make call-with-released capture the current continuation, abort to that prompt, execute the inner thunk in the outer context without the lock acquired, and finally apply the captured continuation to the result. This would mean the above example would end up effectively doing something like this: (let ([tag (make-continuation-prompt-tag)]) (call-with-continuation-prompt tag (lambda () (call-with-semaphore mutex (lambda () (call/comp (lambda (reacquire-k) (abort-current-continuation tag (lambda () (call-with-values (lambda () (call/cc (lambda (k) (stash-continuation-and-abort! k)))) reacquire-k)))) tag)))) (lambda (thunk) (thunk)))) …which sure is wordy, but the real problem is that any continuation marks or prompts installed by the thunk passed to call-with-semaphore/release before calling call-with-released would get dropped. I’ve tried to come up with a way to avoid the needless re-locking outlined above without suffering from that problem, but I haven’t come up with any solutions, not even by bringing mutable state into the picture. Is it possible? Thanks, Alexis -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/BCB3DDF0-95B1-49EB-9FDA-8C3B6FC045DE%40gmail.com. For more options, visit https://groups.google.com/d/optout.