chicken-users
[Top][All Lists]
Advanced

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

Re: [Chicken-users] posix-extras sleep


From: J Altfas
Subject: Re: [Chicken-users] posix-extras sleep
Date: Wed, 20 Feb 2013 01:57:12 -0800

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...)

reply via email to

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