On Tues, 19 Feb 2013 15:13:30 -0600> Jim Ursetto wrote:

> Hmm, I just realized scheduler.scm relies on nanosleep(3) on UNIX, so I guess 
> it is safe to use in posix-extras as well.  I'll change posix-extras to use 
> nanosleep shortly.
>

After all the discussion and further study the merits of nanosleep are clearer, 
and it nicely accommodates the fractional time specifier idea--it really is a 
good match.

Because the idea was interesting I took the liberty to attempt a simple 
implementation of a nanosleep-based scheme sleep function:

(define process-sleep (foreign-lambda* double ((double tm))
#<<PSLP
    struct timespec req;
    struct timespec rem;
    time_t s = (time_t) trunc(tm);
    int r;

        req.tv_sec = s;

     req.tv_nsec = (long) (1000000000.0 * (tm - (double)s));

        r = nanosleep (&req, &rem);

        if (!r) {
            C_return(0.0);
        } else {
            C_return((double) ((double)rem.tv_sec
                                        (rem.tv_nsec / 1000000000.0)));
    }
PSLP
))

A benefit of nanosleep is that if it receives an interrupt during the sleep, 
the "leftover" sleep time is preserved in the second parameter, and so if 
necessary, the sleep can be resumed with that value.  In the above function, if 
the sleep completes, it returns 0.0, but any other value is the unslept 
remainder.

Here's a little driver program to test it out:

(use posix)
(define (sig-int sig)
  2)

(set-signal-handler! 2 sig-int)

(define (sleeper tm)
  (let ((currms (current-milliseconds)))
        (let sleep-lp ((r (process-sleep tm)))
          (if (= r 0)
                (print "Total sleep interval: " (/ (- (current-milliseconds) 
currms) 1000)
                           " seconds.")
                (begin
                  (print "Signal 2:  " r " secs remain..resume sleep....")
                  (sleep-lp (process-sleep r)))))))

(let ((sl (list-ref (argv) 1)))
  (sleeper (string->number sl)))

I used this shell script to interrupt periodically and gave results following.

#!/bin/sh

sleeptm=${1:-"40.0"}

echo "requested sleep time: $sleeptm secs."

proc-sleep $sleeptm &

slpid=`pgrep proc-sleep`

# echo $slpid
chkpid="ps -o pid= -o comm= -p $slpid"

#echo "pid... $($chkpid)"

intsec=$(echo "$sleeptm / 8" | bc -s)
echo "initial sleep interrupt: $intsec sec"
sleep $intsec

chk_sleeper () {
        local n=$1
        intsec=$(($intsec   $n))
        while [ $n -gt 0 ] ; do
                if [ -z "$($chkpid)" ] ; then
                        exit
                else
                        sleep 1
                        n=$((n - 1))
                fi
        done
}

while : ; do
        if [ -z "$($chkpid)" ] ; then
                exit
        fi
        if [ $intsec -gt 1 ] ; then
                printf "After %-2d sec -> " $intsec
                kill -2 $slpid
        fi
        chk_sleeper $(echo "$sleeptm / 4" | bc -s)
done

jra % int-sleep.sh 12.147
requested sleep time: 12.147 secs.
initial sleep interrupt: 1 sec
After 4  sec -> Signal 2:  8.068483725 secs remain..resume sleep....
After 7  sec -> Signal 2:  5.008279345 secs remain..resume sleep....
After 10 sec -> Signal 2:  1.947937168 secs remain..resume sleep....
Total sleep interval: 12.147 seconds.
jra %

Anyway, I'm using /process-sleep/ in my project instead of usleep, et. al., and 
it seems to be working consistently and reliably.  Now if only Windows would 
implement it too, wouldn't that be wonderful?

Thanks,
Jules Altfas.

(Hmm. Some formatting problem is showing up.  Will get it straightened out...)
_______________________________________________
Chicken-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/chicken-users

Reply via email to