From: Jan Hladik
Subject: Function call with timeout
Date: 
Message-ID: <425D294A.9F5E7C05@web.de>
Hi,

I want to call a function f and, if f does not return after (say) 100
seconds of calculation, abort f and continue in the main program. What I
currently do is to use (excl:advise g) to check for a timeout everytime
f calls g, but this has two drawbacks: if g is called to rarely, the
timeout can be significantly exceeded, and if it is called too often,
the check consumes more time than the actual calculation in f.

(mp:with-timeout ) doesn't do what I want either, because it stops after
100 seconds of real-time, not runtime, so my results would depend on the
current load of the machine.

I tried to write something like with-timeout myself, but doesn't work: 

(setf *begin* (get-internal-run-time))

(catch 'timeout
  (mp:process-run-function "watchdog" 
    #'(lambda ()
	(do ((time (get-internal-run-time) (get-internal-run-time)))
	    (nil nil)
	  (sleep 1)
	  (print time)
	  (when (< 100000 (- time *begin*)) ; 100000 milliseconds
	    (throw 'timeout nil))))
	)
  (f))

It throws the timeout after 100 secs of runtime, but then it exits with
the error "tried to throw the non-existent tag 'timeout"

What am I doing wrong?

I would also be thankful for a completely different solution to this
problem.

I use ACL 6.2 under Linux.

TIA,

	Jan

From: Wade Humeniuk
Subject: Re: Function call with timeout
Date: 
Message-ID: <ixb7e.33792$jR3.17720@edtnps84>
Jan Hladik wrote:
> Hi,
> 
> I want to call a function f and, if f does not return after (say) 100
> seconds of calculation, abort f and continue in the main program. What I
> currently do is to use (excl:advise g) to check for a timeout everytime
> f calls g, but this has two drawbacks: if g is called to rarely, the
> timeout can be significantly exceeded, and if it is called too often,
> the check consumes more time than the actual calculation in f.
> 
> (mp:with-timeout ) doesn't do what I want either, because it stops after
> 100 seconds of real-time, not runtime, so my results would depend on the
> current load of the machine.
> 
> I tried to write something like with-timeout myself, but doesn't work: 
> 
> (setf *begin* (get-internal-run-time))
> 
> (catch 'timeout
>   (mp:process-run-function "watchdog" 
>     #'(lambda ()
> 	(do ((time (get-internal-run-time) (get-internal-run-time)))
> 	    (nil nil)
> 	  (sleep 1)
> 	  (print time)
> 	  (when (< 100000 (- time *begin*)) ; 100000 milliseconds
> 	    (throw 'timeout nil))))
> 	)
>   (f))
> 

The problem is that your function runs on an entirely new stack, the
catch does not exist on that stack.  I do not have ACL but in LW it would look
like.  I assume ACL has equivalent functionality.

(defun run-with-run-time (timeout function &rest args)
   (let* ((start-run-time (get-internal-run-time))
          (timer nil))
     (unwind-protect
         (progn
           (setf timer (mp:make-timer
                        (lambda ()
                          (let ((current-run-time (get-internal-run-time)))
                            (when (>= (/ (- current-run-time start-run-time) 
internal-time-units-per-second)
                                      timeout)
                              (mp:unschedule-timer timer)
                              (return-from run-with-run-time  nil))))))
           (mp:schedule-timer-relative timer 1.0 1.0)
           (apply function args))
       (mp:unschedule-timer timer))))


CL-USER 1 > (run-with-run-time 1.0 (lambda () (loop do (get-internal-real-time))))
NIL

CL-USER 2 > (run-with-run-time 1.0 (lambda () (get-internal-real-time)))
1227695

CL-USER 3 >

Wade
From: Jan Hladik
Subject: Re: Function call with timeout
Date: 
Message-ID: <425E5547.2AB306C@web.de>
Wade Humeniuk wrote:
> 
> The problem is that your function runs on an entirely new stack, the
> catch does not exist on that stack.  I do not have ACL but in LW it would look
> like.  I assume ACL has equivalent functionality.

Thank you for your help. Yes, one should assume that ACL has equivalent
functionality, but for some obscure reason, timers belong to the common
graphics package, which apparently can only be used with Windows. :-( I
know several people who switched to LW from ACL, and I wish I had done
the same...

Thanks again,

	Jan
From: Wade Humeniuk
Subject: Re: Function call with timeout
Date: 
Message-ID: <Jwv7e.42554$7Q4.27442@clgrps13>
Jan Hladik wrote:
> Wade Humeniuk wrote:
> 
>>The problem is that your function runs on an entirely new stack, the
>>catch does not exist on that stack.  I do not have ACL but in LW it would look
>>like.  I assume ACL has equivalent functionality.
> 
> 
> Thank you for your help. Yes, one should assume that ACL has equivalent
> functionality, but for some obscure reason, timers belong to the common
> graphics package, which apparently can only be used with Windows. :-( I
> know several people who switched to LW from ACL, and I wish I had done
> the same...
> 

Here is a version without a timer.  I read the ACL docs for
multiprocessing.  If I am not mistaken this will also work
on ACL. (though the doc on the ACL version of process-interrupt
is not entirely clear to me on what to expect)

(defun run-with-run-time (timeout function &rest args)
   (let* ((start-run-time (get-internal-run-time))
          (watched-process mp:*current-process*)
          (watchdog (mp:process-run-function
                     "watchdog" #+lispworks nil
                     (lambda ()
                       (prog ()
                         not-yet
                         (sleep 1.0)
                         (if (>= (/ (- (get-internal-run-time) start-run-time)
                                    internal-time-units-per-second)
                                 timeout)
                             (mp:process-interrupt watched-process
                                                   (lambda ()
                                                     (return-from run-with-run-time nil)))
                           (go not-yet)))))))
     (unwind-protect
         (apply function args)
       (mp:process-kill watchdog))))

CL-USER 7 > (run-with-run-time 1.0 (lambda () (get-internal-real-time)))
811848

CL-USER 8 > (run-with-run-time 1.0 (lambda () (loop do (get-internal-real-time))))
NIL

CL-USER 9 >

Wade
From: Jan Hladik
Subject: Re: Function call with timeout
Date: 
Message-ID: <425E9B92.37DB79F0@web.de>
Wade Humeniuk wrote:
> 
> Here is a version without a timer.  I read the ACL docs for
> multiprocessing.  If I am not mistaken this will also work
> on ACL. (though the doc on the ACL version of process-interrupt
> is not entirely clear to me on what to expect)

Thank you very much! I tested it, and it works just like it should! 

(I actually thought about posting a link for the ACL documentation here,
but I thought asking you to deal with the limitations of my compiler
would be asking too much.)

You have just made my life (well, let's say its professional part) a lot
easier. 

Cheers,

	Jan
From: Wade Humeniuk
Subject: Re: Function call with timeout
Date: 
Message-ID: <eRz7e.30616$yV3.1905@clgrps12>
Jan Hladik wrote:
> Wade Humeniuk wrote:
> 
>>Here is a version without a timer.  I read the ACL docs for
>>multiprocessing.  If I am not mistaken this will also work
>>on ACL. (though the doc on the ACL version of process-interrupt
>>is not entirely clear to me on what to expect)
> 
> 
> Thank you very much! I tested it, and it works just like it should! 
> 

That's good and Your Welcome.  It seems the ACL and LW MP packages
work very similarily.  As for your request for a a timer system
for ACL, it could be implemented as a controlling timer process that queues
timers for expiry.  When a timer has expired it could use process-interrupt
just like run-with-run-time does.

Wade
From: jayessay
Subject: Re: Function call with timeout
Date: 
Message-ID: <m3r7hbel2e.fsf@rigel.goldenthreadtech.com>
Wade Humeniuk <··················@telus.net> writes:

> Here is a version without a timer.  I read the ACL docs for
> multiprocessing.  If I am not mistaken this will also work
> on ACL. (though the doc on the ACL version of process-interrupt
> is not entirely clear to me on what to expect)

<snip code>

Wow.  Here is what I would have expected:

(defun run-with-run-time (timeout cleanup-function function &rest args)
  (mp:with-timeout (timeout cleanup-function)
    (apply function args)))

Ex:

(defun foo (n)
  (dotimes (i n)
    (sleep 0.5))
  :success)

(run-with-run-time 3 "Failed" #'foo 1)
==> :success

(run-with-run-time 3 "Failed" #'foo 10)
==> "Failed"



/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: jayessay
Subject: Re: Function call with timeout
Date: 
Message-ID: <m3vf6nelm3.fsf@rigel.goldenthreadtech.com>
Jan Hladik <······@web.de> writes:

> Wade Humeniuk wrote:
> > 
> > The problem is that your function runs on an entirely new stack, the
> > catch does not exist on that stack.  I do not have ACL but in LW it
> > would look like.  I assume ACL has equivalent functionality.
> 
> Thank you for your help. Yes, one should assume that ACL has equivalent
> functionality, but for some obscure reason, timers belong to the common
> graphics package, which apparently can only be used with Windows. :-( I
> know several people who switched to LW from ACL, and I wish I had done
> the same...

This sounds like complete rubbish.  The following ACL function is
available on both UNI*/Linux and Windows:

mp:with-timeout

(mp:with-timeout (<seconds-available-for-running>
                  <cleanup-forms-on-timer-fire>)
  <code to run while counting down seconds-available-for-running>)

How does that not work for you???


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Wade Humeniuk
Subject: Re: Function call with timeout
Date: 
Message-ID: <H2Y7e.34864$vt1.17386@edtnps90>
jayessay wrote:

> 
> This sounds like complete rubbish.  The following ACL function is
> available on both UNI*/Linux and Windows:
> 

You should re-read the original post:

 From the original --

(mp:with-timeout ) doesn't do what I want either, because it stops after
100 seconds of real-time, not runtime, so my results would depend on the
current load of the machine.

-- end

Wade
From: jayessay
Subject: Re: Function call with timeout
Date: 
Message-ID: <m3mzruef4k.fsf@rigel.goldenthreadtech.com>
Wade Humeniuk <··················@telus.net> writes:

> jayessay wrote:
> 
> > This sounds like complete rubbish.  The following ACL function is
> > available on both UNI*/Linux and Windows:
> >
> 
> You should re-read the original post:

Good point...

/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com