It is common to automatically close files, sockets, and other resources when the program uses a continuation (or exception, which is often implemented using continuations) to exit a context. There are often library procedures that help do this automatically; for example, see Racket's call-with-input-file*, call-with-semaphore, etc. They all use dynamic-wind
in their implementation.
It's often difficult to write code that uses or manages resources correctly in the presence of continuations. For example, if a file gets closed when control jumps out, should it be re-opened when control jumps back in? If so, maybe it needs to be opened in a different mode the second time, eg append instead of truncate. But now it may be difficult to ensure that the output is well-formed; continuation jumps may mean that parts get written multiple times, out of order, etc. And so on. So it's often useful to simply prohibit continuation jumps back into a context once it's been exited. Racket provides call-with-continuation-barrier
for this purpose, but it can also be done with dynamic-wind
and a mutable variable.
(One difference between using call-with-continuation-barrier
and dynamic-wind
is that you use call-with-continuation-barrier
around your call to unknown code, whereas dynamic-wind
would need to be around the beginning of the code that you want to protect from reentry, which may be harder to determine. There's a mailing-list post with more detailed discussion.)
The story is about the same for delimited continuations. For example, shift
jumps out across boundaries, and applying the procedure it gives you jumps in across the captured context boundaries.