unwind-protect.rkt
#lang racket/base

(require (prefix-in finalize: "finalize.ss"))

(define (unwind-protect thunk cleanup)
   (call/cc
    (λ (continuation)
      (finalize:register continuation (λ (value) (cleanup)))
      (thunk))))

(define (rewind-protect thunk cleanup)
   (let ((re-entering? #f))
     (dynamic-wind
      (λ ()
        (when re-entering?
          (raise-user-error
           (format
            "~s has already been called ~s may not be entered again."
            cleanup
            thunk)))
        (set! re-entering? #t))
      thunk
      cleanup)))

(provide unwind-protect rewind-protect)