[plt-scheme] semaphore-like event

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Mon Jul 20 18:45:09 EDT 2009

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
      (lambda ()
        (sync (nack-guard-evt (lambda (nack)
                                (channel-put nack-channel nack)
   (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?


Posted on the users mailing list.