From: Dave Bakhash
Subject: a WITH-TIMEOUT type of macro in LW
Date: 
Message-ID: <8a3667a0.0201201303.9cd9024@posting.google.com>
Hi,

Do any LispWorks people have a simple macro to try to run a form which
will time out with some kind of condition if the form (or body)
doesn't return in some amount of time?

thanks,
dave

From: Jochen Schmidt
Subject: Re: a WITH-TIMEOUT type of macro in LW
Date: 
Message-ID: <3C4B4635.6070809@dataheaven.de>
Dave Bakhash wrote:
> Hi,
> 
> Do any LispWorks people have a simple macro to try to run a form which
> will time out with some kind of condition if the form (or body)
> doesn't return in some amount of time?


Taken (modified) from my ACL-COMPAT module of Portable AllegroServe:

(defun invoke-with-timeout (timeout bodyfn timeoutfn)
   (block timeout
     (let* ((process mp:*current-process*)
            (timer (mp:make-timer
                         #'(lambda ()
                              (mp:process-interrupt
                                          process
                                         #'(lambda ()
                                             (return-from timeout
                                               (funcall timeoutfn))))))))
       (mp:schedule-timer-relative timer timeout)
       (unwind-protect (funcall bodyfn)
         (mp:unschedule-timer timer)))))

(defmacro with-timeout ((seconds &body timeout-forms) &body body)
   (let ((-body-form- (gensym "WT-BODY-"))
         (-timeout-form- (gensym "WT-TIMEOUT-")))
     `(flet ((,-body-form- () ,@body)
             (,-timeout-form- () ,@timeout-forms))
       (invoke-with-timeout ,seconds #',-body-form-
                                     #',-timeout-form-))))


You can test it with:

(with-timeout (5 (print 'timeout))
   (sleep 10))

and

(with-timeout (10 (print 'timeout))
   (sleep 5))


ciao,
Jochen
From: Kaz Kylheku
Subject: Re: a WITH-TIMEOUT type of macro in LW
Date: 
Message-ID: <GDH28.6169$V_4.148039@news3.calgary.shaw.ca>
In article <················@dataheaven.de>, Jochen Schmidt wrote:
>(defmacro with-timeout ((seconds &body timeout-forms) &body body)
>   (let ((-body-form- (gensym "WT-BODY-"))
>         (-timeout-form- (gensym "WT-TIMEOUT-")))
>     `(flet ((,-body-form- () ,@body)
>             (,-timeout-form- () ,@timeout-forms))
>       (invoke-with-timeout ,seconds #',-body-form-
>                                     #',-timeout-form-))))

Why the gensyms and flet, when you can just use two lambda expressions?

(defmacro with-timeout ((seconds &body timeout-forms) &body body)
 `(invoke-with-timeout ,seconds #'(lambda () ,@body) 
                                #'(lambda () ,@timeout-forms)))

Do you find that using local functions with gensym names that have
descriptive prefixes enhances readability of the expanded form?
From: Jochen Schmidt
Subject: Re: a WITH-TIMEOUT type of macro in LW
Date: 
Message-ID: <3C4B6F98.9050404@dataheaven.de>
Kaz Kylheku wrote:
> In article <················@dataheaven.de>, Jochen Schmidt wrote:
> 
>>(defmacro with-timeout ((seconds &body timeout-forms) &body body)
>>  (let ((-body-form- (gensym "WT-BODY-"))
>>        (-timeout-form- (gensym "WT-TIMEOUT-")))
>>    `(flet ((,-body-form- () ,@body)
>>            (,-timeout-form- () ,@timeout-forms))
>>      (invoke-with-timeout ,seconds #',-body-form-
>>                                    #',-timeout-form-))))
>>
> 
> Why the gensyms and flet, when you can just use two lambda expressions?
> 
> (defmacro with-timeout ((seconds &body timeout-forms) &body body)
>  `(invoke-with-timeout ,seconds #'(lambda () ,@body) 
>                                 #'(lambda () ,@timeout-forms)))
> 
> Do you find that using local functions with gensym names that have
> descriptive prefixes enhances readability of the expanded form?

Hm.. I have to say I do not really remember why I did it the way it is 
now. But you are right - it is nicer if I simply use two lambdas here...

thanks,
Jochen