regenerate.ss
#lang scheme/base

(require (prefix-in log: (planet synx/log:1))
         (prefix-in finalize: (planet synx/util:1/finalize))
         (planet synx/util:1/later))

(define collect-garbage-later (later 1 collect-garbage))

; maybe if we make a sorted list of resources by date?

(define closable (vector))

(define (move-to-closable! v)
  (set! closable (vector-append (vector-filter
                                 (λ (test) (not (eq? test v)))
                                 closable)
                                (vector v))))

(define (move-from-closable! v)
    (set! closable (vector-filter
                    (λ (test) (not (eq? test v)))
                    closable)))

(define (regenerating-resource i open close)
  (define resource (make-box #f))
  (λ ()
    (set! resources (vector-append (vector-filter
                                    (λ (test) (not (eq? test resource)))
                                    resources)
                                   (vector resource)))
    (let ((value (weak-box-value resource)))
       (if value
           value
           (let retry ((retries 0) (index 0))
             (let ((index
                    (for/first ((index (in-range index (vector-length resources))))
                      (and (weak-box-value (vector-ref resources index))
                           index))))
               (let ((saved (vector-ref resources index)))
                 (set! resources
                       (vector-filter
                        (λ (test) (not (eq? test saved)))))
                 (let ((value (weak-box-value saved)))
                   (when value
                     (close value)))))
             (or (with-handlers
                     (((λ (e)
                         (and (< retries 10)
                              (exn:fail? e)))
                       (λ (e) #f)))
                   (let ((value (open)))
                     (finalize:register value close)
                     (set! resource (make-weak-box value))
                     value))
                 (begin
                   (log:info "~s retry ~s" i retries)
                   (collect-garbage-later)
                   (semaphore-post semaphore)
                   (sleep 0)
                   (semaphore-wait semaphore)
                   (retry (+ retries 1))))))))))

(define (reopening-input-file i name)
  (regenerating-resource
   i
   (λ () (open-input-file name))
   close-input-port))

(define (sploof-one-file i)
  (λ ()
    (define f (reopening-input-file i "/dev/zero"))
    (display (format "~s File is ~s~n" i (f)))
    (display (format "~s~n" (read-bytes 4 (f))))))
  
(define (main)
  (for-each
   sync/enable-break
   (map thread-dead-evt
        (for/list ((i (in-range #x1800)))
          (thread (sploof-one-file i))))))

(provide main)