Next: iklib unwind-protect syntaxes, Up: iklib unwind-protect [Index]
The syntax with-unwind-handler implements the core mechanism;
with-unwind-protection is an alias for it.
unwind-protect offers a syntax similar to the one of the Common
Lisp macro with the same name.  The former is meant to be used as
follows:
#!vicare
(import (vicare))
(let ((port (open-file-output-port "file.ext")))
  (with-unwind-handler
      (lambda (why)
        (close-output-port port))
    (lambda ()
      (put-bytevector port '#ve(ascii "ciao")))))
and the latter as follows:
#!vicare
(import (vicare))
(let ((port (open-file-output-port "file.ext")))
  (unwind-protect
      (put-bytevector port '#ve(ascii "ciao"))
    (close-output-port port)))
first we allocate a resource (in this case the port); then we use it in the body forms; finally we release it in the clean–up forms.
When using the mechanism:
dynamic-wind calls.  These would be nasty
errors, because the dynamic environment would get corrupted and recovering correctly
might be impossible; so we must really write and debug such in–guard and
out–guard thunks with care.
(with-exception-handler
    (lambda (E)
      (with-blocked-exceptions
        (lambda ()
          (handle E))))
  (lambda ()
    (do-something-useful)))
but it is not very satisfying. Another possibility is:
(define-condition-type &originally-raised
    &condition
  make-originally-raised-condition
  originally-raised-condition?
  (object originally-raised-object))
(with-exception-handler
    (lambda (E)
      (with-exception-handler
          (lambda (X)
            (raise-continuable
              (condition X
                (make-originally-raised-condition E))))
        (lambda ()
          (handle E))))
  (lambda ()
    (do-something-useful)))
If the bodacious answer to both the decisions is “We trust”: we can nest at will
uses of with-unwind-protection:
(define (outer)
  (with-unwind-protection
      (lambda (why)
        (outer-unwind-handler))
    (lambda ()
      (do-something-useful)
      (inner))))
(define (inner)
  (with-unwind-protection
      (lambda (why)
        (inner-unwind-handler))
    (lambda ()
      (do-some-other-useful-thing))))
(outer)
beware: unwind handlers are evaluated in the dynamic environment of the use
of with-unwind-protection.
Otherwise we must avoid error handlers to cause the execution flow to
cross an unwind protection boundary; we can do it by using compensations
and the standard guard syntax:
(define (outer)
  (push-compensation-thunk
    (lambda ()
      (outer-unwind-handler)))
  (do-something-useful)
  (inner))
(define (inner)
  (push-compensation-thunk
    (lambda ()
      (inner-unwind-handler)))
  (do-some-other-useful-thing))
(with-compensations
  (with-blocked-exceptions
    (lambda ()
      (guard (E ((type-one-error? E)
                 (handle E))
                (else
                 (do-something-dammit!!!)))
        (outer)))))
or by using the compensations and the try syntax defined by
Vicare:
(define (outer)
  (push-compensation-thunk
    (lambda ()
      (outer-unwind-handler)))
  (do-something-useful)
  (inner))
(define (inner)
  (push-compensation-thunk
    (lambda ()
      (inner-unwind-handler)))
  (do-some-other-useful-thing))
(with-compensations
  (with-blocked-exceptions
    (lambda ()
      (try
          (outer)
        (catch E
          ((&type-one)
           (handle E))
          (else
           (do-something-dammit!!!)))))))
beware: compensation handlers are evaluated in the dynamic environment of
the use of with-compensations.
Next: iklib unwind-protect syntaxes, Up: iklib unwind-protect [Index]