#lang scheme/base

(define will (make-will-executor))

(define executor
  (thread
   (λ ()
     (let loop ()
       (will-execute will)
       (loop)))))

(define (unwind-protect startup shutdown)
    (will-register
     will
     (let loop ((n 0))
       (if (> n 10)
           (startup) ; fail for real this time
           (or
            (with-handlers
                ((exn:fail:filesystem? (λ (e) (collect-garbage) #f)))
              (startup))
            (loop (+ n 1)))))
     shutdown))

(define (auto-open-input-file name #:mode (mode 'binary))
  (unwind-protect
   (λ () (open-input-file name #:mode mode))
   close-input-port))

(define (auto-open-output-file name #:mode (mode 'binary) #:exists (exists 'error))
  (unwind-protect
   (λ () (open-output-file name #:mode mode #:exists exists))
   close-output-port))

(define (main)
  (let loop ((n 0))
    (let ((source (auto-open-input-file "/dev/null"))
          (flarn (auto-open-output-file "/dev/null" #:exists 'append)))
      (display (format "Iteration ~s~n" n)))
    (loop (+ n 1))))

(provide 
 main
 (rename-out
  (auto-open-input-file open-input-file)
  (auto-open-output-file open-output-file)))