[plt-scheme] semaphore-like event
I'm trying to make an event that is initially not ready, but once a
'release' operation is performed, it is ready forever afterwards. In
particular, it becomes ready in synchronizations that have already
started and are currently blocked. (Imagine if semaphores supported an
operation that bumped the semaphore's internal counter to +inf.0. That
would do it.)
My question: Is there a way to do this without creating an extra thread?
I can do this with an extra thread in a number of ways. The simplest
way I've found is to use the thread's death itself as the event:
;; make-event+release/thread-death : -> (values evt (-> void))
(define (make-event+release/thread-death)
(define s (make-semaphore 0))
(define th (thread (lambda () (semaphore-wait s))))
(values (thread-dead-evt th)
(lambda () (semaphore-post s))))
I can also do this using a thread and a nack-guard event. (I think so,
anyway. My understanding of nack-guard-evt is pretty shaky.)
;; make-event+release/thread-nack : -> (values evt (-> void))
(define (make-event+release/thread-nack)
(define s (make-semaphore 0))
(define nack-channel (make-channel))
(define th
(thread
(lambda ()
(sync (nack-guard-evt (lambda (nack)
(channel-put nack-channel nack)
never-evt))
s))))
(values (channel-get nack-channel)
(lambda () (semaphore-post s))))
The only way I've found that doesn't involve creating a thread is to
create a port and use its progress event (which may involve another
thread behind the scenes; I don't know).
;; make-event+release/port-progress : -> (values evt (-> void))
(define (make-event+release/port-progress)
(define p (open-input-string "x"))
(define evt (port-progress-evt p))
(values evt
(lambda () (read-char p))))
Any easier ways out there? Any bugs in the code I've posted?
Ryan