Allow program to have many (10 max in this example) independent alarms for time intervals >= 0.01 sec.
These alarms don't conflict with standart alarm(). Standart sleep() will be canceled when one of alarm's signal arrives.
Each alarm require 1 file descriptor, 1 signal handler between SIG50..59 and 1 forked process taking no CPU time, only memory.
Realization of cron-like system based on one such alarm and realization of sleep() which will not cancel when signal arrives left as exercise for reader. :-)
# just "macro" function from our library sub Cat { local *F; open F, "< ".$_[0] or return; local $/ unless wantarray; return <F>; } { my $SYS_setitimer = ( join("", map { Cat("/usr/include/$_.h") } qw(syscall sys/syscall bits/syscall asm/unistd) ) =~ /^\s*#define\s*(?:__NR|SYS)_setitimer\s*(\d+)/m )[0]; my %ALARM = (); # $n = alarm_start(0.01, \$counter) or die; # $n = alarm_start(2.50, \&handler) or die; # alarm_stop($n); sub alarm_start { my ($PARENT, $time, $counter) = ($$, @_); return unless my ($n) = grep { not exists $ALARM{$_} } 50..59; @{$ALARM{$n}}{"sec","usec"} = (int($time), int(($time-int($time))*1000000)); $SIG{"NUM".$n} = ref($counter) eq "SCALAR" ? sub {$$counter++} : $counter; pipe $ALARM{$n}{READ}, $ALARM{$n}{WRITE}; if (!fork()) { $0 .= " ALARM $n"; close $ALARM{$n}{WRITE}; $SIG{ALRM} = sub { kill $n, $PARENT }; # FIXME 0 mean ITIMER_REAL from <sys/time.h> syscall $SYS_setitimer, 0, pack("llll", (@{$ALARM{$n}}{"sec","usec"})x2), "\x00"x16; read $ALARM{$n}{READ}, my $buf, 1; print "Chield $n died\n"; exit; } close $ALARM{$n}{READ}; return $n; } sub alarm_stop { $SIG{"NUM".$_[0]} = "IGNORE"; print {$ALARM{$_[0]}{WRITE}} "\n" if exists $ALARM{$_[0]}; delete $ALARM{$_[0]}; } } # Example: $n1 = alarm_start(0.001, \$c1) or die 1; $n2 = alarm_start(0.01, \$c2) or die 2; $n3 = alarm_start(0.1, \$c3) or die 3; $n4 = alarm_start(1, \$c4) or die 4; $n5 = alarm_start(1.5, \$c5) or die 5; $n6 = alarm_start(0.02, sub { $c6++ }) or die 6; $t0 = time(); $i++ while time()<$t0+10; print "Parent died: i=$i c1=$c1 c2=$c2 c3=$c3 c4=$c4 c5=$c5 c6=$c6\n";

Replies are listed 'Best First'.
Re: Simultaneous alarms < 1 sec
by powerman (Friar) on Feb 10, 2003 at 06:19 UTC
    Btw, is anybody know is recv()/send() reentrant? Using these alarms for async IO looks very interesting if recv()/send() is reentrant.
    I've readed all information about non-reentrant functions issue found in glibc documentation, but as far as I understand recv/send at high-level realized in perl, and at low-level realized in kernel, not in glibc. I'm 99% sure what in kernel recv/send MUST be reentrant, but I don't see any information about perl part of these functions. Tests can't answer to this question with 100% guarantie... :(