#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))
(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)