This is the mail archive of the guile@cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Using async's in Guile.


Mikael Djurfeldt wrote:
> "Bradley M. Kuhn" <bkuhn@ebb.org> writes:
> 
> > When I do figure this out, would it be worth it to write a tutorial on using
> > these async functions?  I didn't find them documented in the current CVS
> > tree.  If I did write such documentation, where would it belong?
 
> No, at least not yet.  Until further notice the asyncs should be
> considered "internal guts" of Guile.  It is planned to make a rewrite of
> the signal handling mechanisms when we adapt Guile for POSIX threads.
> Asyncs may not even exist after that.

Hmmm...so, what is the best way now to handle a case where I need a clock to
invoke some function after a specified amount of time.

Right now, I am using a clock implementation that uses SIGALRM underneath.

I would like something a bit more versatile.


Any suggestions?  Attached is my current implementation of the clock.

-- 
         -  bkuhn@ebb.org  -  Bradley M. Kuhn  -  bkuhn@gnu.org  -
                          http://www.ebb.org/bkuhn
; clock-using-alarms.scm                                      -*- Scheme -*-

; Code for engines based on  Dorai Sitaram's:
;  http://www.cs.rice.edu/~dorai/t-y-scheme/t-y-scheme-Z-H-16.html
;   To get a clock in Guile, we use SIGALRM

; We need a consistent clock interface, as the document suggests
;   For Guile, we use the alarm mechanism.  This allows for only one
;   clock at a time.  :(

; As stated in Sitaram:
; clock allows the following operations:

; 1) (clock 'set-handler h) sets the interrupt handler to h.

; 2) (clock 'set n) resets the clock's remaining ticks to n,
;    returning the previous value.

; Mine works like that, but it is wrapped in an object, so I get:
;   ((clock 'set-handler!) h) 
;      and
;   ( (clock 'set-time!) n)

; Note:  If you have multiple clocks floating around, they will effect each
;        other---if you turn one off, they are all off, and the will all 
;        call the handler at the minimum of when they were set.
;        This problem occurs because there is only one SIGALRM.  I have
;        searched for a way around this problem but to no avail.

(define make-clock
  (lambda () 
              (letrec ( (time-amount 'infinity) 
                        (handler     '() )
                        (have-handler #f )
                        (old-handler (car (sigaction SIGALRM)))
                        (reset-alarms (lambda ()
                                     ; First, if we have and "infinity" clock,
                                     ; Then we don't have to have our handler
                                     (if (eq? time-amount 'infinity)
                                         ; Set the fact that we don't have
                                         ; a handler
                                         (set! have-handler #f)
                                         ; Otherwise, as long as time is >= 0,
                                         ; note that we have a handler, start
                                         ; countdown using alarm
                                     (if (< time-amount 0)
                                         (error
                                          "clock cannot have time < 0")
                                         (begin 
                                           (set! have-handler #t)
                                           (alarm time-amount))))) )

                   )
                (sigaction SIGALRM 
                           (lambda (x)
                             (if have-handler 
                                 (handler))
                             (if (procedure? old-handler) (old-handler x))))

                (lambda (message)
                  (case message
                    ( (set-time!)   (lambda (x) 
                                      (let ( (old-time time-amount) )
                                        (set! time-amount x)
                                        (reset-alarms)
                                        old-time)))
                    
                    ( (set-handler!)   (lambda (x) 
                                         (set! have-handler #t)
                                         (set! handler x)
                                         (reset-alarms) ) )
                    )))))

;******************************************************************************
(define test-clock
  (lambda ()
    (begin
      (let (
            (clock1 (make-clock))
            (clock2 (make-clock))  ) 
      ((clock1 'set-handler!)
       (lambda () (writeln "clock1's handler has come!")))
      ((clock2 'set-handler!)
       (lambda () (writeln "clock2's handler has come!")))

      ( (clock2 'set-time!) 7)
      (display "First Time: ")

      (display ( (clock1 'set-time!) 5)) (newline)
      (sleep 3)
      (display "Second Time: ")
      (display ( (clock1 'set-time!) 10)) (newline)
      (sleep 9)
      (display "Handler error should come in one second!!") (newline)
    ))))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]