guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: module anoouncement


From: Neil Jerram
Subject: Re: module anoouncement
Date: Tue, 16 Aug 2005 20:25:25 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050513 Debian/1.7.8-1

Tano Fotang wrote:
> Dear all:
> Just got a small module `gev' that provides asynchrony for guile 
> programs, so that trigger functions (callbacks) can be registered for 
> some common tasks such as timers and the checking i/o ports.

Hi Tano,

This looks quite useful.  I know that I've written code on these lines
many times in the past, so hopefully someone (or even me next time) will
appreciate that you've now packaged it up into a module.

I have 3 comments on your API.

1. It would be more Schemely to omit the user-data parameters
everywhere.  You never need such parameters in Scheme, because you can
instead wrap any amount of context up in the closure of the callback
procedure <proc>.

In other words, wherever one would write, with your API, something like
this:

  (gev:add-timer 10
                 (lambda (user-data)
                   ...)
                 (get-user-data-for-timer))

you can instead write this:

  (gev:add-timer 10
                 (let ((user-data (get-user-data-for-timer)))
                   (lambda ()
                     ...)))

2. It seems inconsistent to use IDs in some cases for the remove
procedures, and the setup parameters in others.  I suggest you consider
using some form of ID in all cases.

3. You might want to extend this infrastructure by using continuations
to provide apparently synchronous versions of these APIs.

What do I mean by that?  Something like this:

  (define (gev:sleep interval)
    (call/cc
      (lambda (cont)
        (gev:add-timer interval
                       (lambda ()
                         (cont #t)))
        (gev:loop))))

You can either put the (gev:loop) as here, or assume that there is an
outer (gev:loop) running somewhere, and use a (throw ...) here to throw
to that loop.  The API user can then write code where the (gev:sleep)
appears to be a blocking sleep, but which actually runs the (gev:loop)
during the sleep:

  (begin
    ...
    (display "About to sleep\n")
    (gev:sleep 10)
    (display "Ah, I needed that\n")
    ...)

Similarly you can implement apparently blocking reads/writes which don't
actually block (and which may be easier to use than the asynchronous
versions).

Best regards,
        Neil




reply via email to

[Prev in Thread] Current Thread [Next in Thread]