alarm() and later()

20 views
Skip to first unread message

Gaal Yahas

unread,
Apr 18, 2005, 4:04:23 PM4/18/05
to perl6-l...@perl.org
Two things popped up while implementing a demo version of alarm() today.

1. In perl5 and in most underlying libraries, alarm() has 1 second
granularity (and a possible 1 second error on top of that). Can we have
the alarm builtin not assume the worst, and take a Num instead of an
Int, so that on some systems at least we get higher resolution sleeps?

2. Since signals are so global and sometimes we want something else,
how about a variation on the traditional u?alarm theme, in which you can
pass an optional closure to alarm() that will get called back instead of
having a SIGALRM raised?

multi sub alarm(: Num ?$timeout = $CALLER::_,
Num ?$interval,
Code ?$callback) returns Int

This should be reentrant and allow multiple uses. The Int return is an
id on the future event so you can cancel it. (Which needs speccing.
Possibly this could return a reference to some object instead of an
id?) If the alarm builtin is getting too overloaded, I propose the
closure version be named "later".


--
Gaal Yahas <ga...@forum2.org>
http://gaal.livejournal.com/

Larry Wall

unread,
Apr 20, 2005, 1:11:35 PM4/20/05
to perl6-l...@perl.org
On Wed, Apr 20, 2005 at 08:20:04AM +0200, Leopold Toetsch wrote:
: I can't say anything about the actual Perl6 syntax, but Parrot provides
: sub-second resolution as well as alarm callbacks and of course multiple
: timers.

We will certainly be pushing all the time interfaces of Perl 6 toward
using floating-point time values. The only question is whether alarm()
is the right name for one of the interfaces, and whether we even need an
interface whose *default* behavior is to send a signal, ugh. We should
probably be encouraging timed callbacks instead. We could even force
people to define their own alarm if they want one. Assuming we
rehuffmanize "kill" to "sendsignal" or some such, we have:

sub alarm ($secs) {
{ sendsignal $*PID, Signal::ALARM }.cue(:delay($secs));
}

Though I suppose people really mostly just want something like

sub alarm ($secs) {
{ sendsignal $*PID, Signal::ALARM }.delay($secs);
}

The actual verb/adverb names are negotiable, but they need to handle
relative vs absolute times intuitively. Different words have different
connotations in that regard. "delay" is definitely relative, while
"after" tends toward absolute, though can be used relatively too.
"at" is definitely absolute time, but maybe too overloaded with
positional meanings. "later" is unfortunately completely ambiguous.

By the way, I was tempted to make it "sendsig", but then I started
wondering what it would mean to send a sigil or a signature...

In any event (no pun intended), I've always wondered how it is you
can "kill" a process with a SIGCONT. As long as we're fixing everything
else, maybe we can fix Unix too. :-)

Larry

Gaal Yahas

unread,
Apr 20, 2005, 2:29:17 PM4/20/05
to perl6-l...@perl.org
On Wed, Apr 20, 2005 at 10:11:35AM -0700, Larry Wall wrote:
> We will certainly be pushing all the time interfaces of Perl 6 toward
> using floating-point time values. The only question is whether alarm()
> is the right name for one of the interfaces, and whether we even need an
> interface whose *default* behavior is to send a signal, ugh. We should
> probably be encouraging timed callbacks instead. We could even force
> people to define their own alarm if they want one. Assuming we
> rehuffmanize "kill" to "sendsignal" or some such, we have:

(FWIW, this is called "signalProcess" in Haskell.)

> sub alarm ($secs) {
> { sendsignal $*PID, Signal::ALARM }.cue(:delay($secs));
> }
>
> Though I suppose people really mostly just want something like
>
> sub alarm ($secs) {
> { sendsignal $*PID, Signal::ALARM }.delay($secs);
> }
>
> The actual verb/adverb names are negotiable, but they need to handle
> relative vs absolute times intuitively. Different words have different
> connotations in that regard. "delay" is definitely relative, while
> "after" tends toward absolute, though can be used relatively too.
> "at" is definitely absolute time, but maybe too overloaded with
> positional meanings. "later" is unfortunately completely ambiguous.

We also want repeat events; I can think of two ways to do it. Either
require everything to be explicit with adverbs, or have the closure's
return value determine whether to keep calling back or to quit. GLib
does the latter, and there's a cleanliness in how the closure itself can
control when to stop, but the former means you can schedule arbitrary
code without changing it.

Is there anybody from the perl-loop gang around here? I'm sure they've
thought about these things a lot.

Larry Wall

unread,
Apr 20, 2005, 3:24:42 PM4/20/05
to perl6-l...@perl.org
On Wed, Apr 20, 2005 at 09:29:17PM +0300, Gaal Yahas wrote:
: (FWIW, this is called "signalProcess" in Haskell.)

Also in the FWIW department, I mislike mixed-case identifiers for
anything in the "core". That sort of things screams "user-defined"
to me.

To a lesser extent, I also tend to avoid underscores in the core
unless I'm trying to be obnoxious: DONT_EVER_USE_THIS_FEATURE(1).

: We also want repeat events; I can think of two ways to do it. Either


: require everything to be explicit with adverbs, or have the closure's
: return value determine whether to keep calling back or to quit. GLib
: does the latter, and there's a cleanliness in how the closure itself can
: control when to stop, but the former means you can schedule arbitrary
: code without changing it.

I think the conceptual default for callbacks should be single call,
with the return value reserved for returning actual data to whatever
context calls it. It's easy enough to have a special call that says
something like call_me_again(). Er, callmeagain()... :-)

You also have the ability to schedule repeated calls externally to the
closure, presumably. In general, I think that's even cleaner than
usurping the return value. I'm presuming we also give the closure
some way to get at its scheduler handle so it can remove itself from
repeats, or otherwise give it some kind of dont_call_me_again(). Er...

All that being said, it doesn't actually make a lot of sense to return
user data to the scheduler. Unless, that is, the scheduler is also
managing some kind of pipeline and will feed that return value to
some other code. But then, timed generators are nice for lots of
simulation applications. (But then you start getting into discrete
event simulations where you want to simulate the flow of time as well,
where delay() isn't really a real delay, but just waits till virtual
time gets far enough. Well, that's enough brain strain for now.)

Larry

Uri Guttman

unread,
Apr 20, 2005, 7:05:43 PM4/20/05
to Gaal Yahas, perl6-l...@perl.org
>>>>> "GY" == Gaal Yahas <ga...@forum2.org> writes:

>> sub alarm ($secs) {
>> { sendsignal $*PID, Signal::ALARM }.cue(:delay($secs));
>> }
>>
>> Though I suppose people really mostly just want something like
>>
>> sub alarm ($secs) {
>> { sendsignal $*PID, Signal::ALARM }.delay($secs);
>> }
>>
>> The actual verb/adverb names are negotiable, but they need to handle
>> relative vs absolute times intuitively. Different words have different
>> connotations in that regard. "delay" is definitely relative, while
>> "after" tends toward absolute, though can be used relatively too.
>> "at" is definitely absolute time, but maybe too overloaded with
>> positional meanings. "later" is unfortunately completely ambiguous.

GY> We also want repeat events; I can think of two ways to do it. Either
GY> require everything to be explicit with adverbs, or have the closure's
GY> return value determine whether to keep calling back or to quit. GLib
GY> does the latter, and there's a cleanliness in how the closure itself can
GY> control when to stop, but the former means you can schedule arbitrary
GY> code without changing it.

GY> Is there anybody from the perl-loop gang around here? I'm sure they've
GY> thought about these things a lot.

i do a fair amount of event loop stuff in perl and have worked on
various apis for it. i have a few rfc's which try to tie in timers and
signals and async io with perl6's i/o functions (none of which are
defined yet).

the good news is that parrot will be providing a clean core event loop
mechanism using native kernel threads and event queues.

what a proper event loop program needs is an event loop run core or
module. it would block on reading the event queue and dispatch events
(via callbacks) as they get read in.

also you need to let go of flow control to an event loop. otherwise you
will be running 100% cpu until you block hard and the event loop can't
run again. the problem is that if you use callbacks and no threads, you
must have an event loop take over. parrot will not offer this directly
but it will be easy to create one on top of the event queue it
provides.

most uses of simple alarms now are sleep timers and breaking out of
blocking calls with die. anything more complex (even 2 timers at one
time) need a proper event loop and proper control over creating and
handling them.

signal handling can be a subset of the event loop (which is good, as
that means they can get delivered synchronously and not be a worry like
they used to be in p5 without event loops).

so the biggest difference with larry's api is that you need to specify a
callback (method or code ref or either?) in the call that sets up a
timer. and you need several options so it should be a key/value api with
good defaults. here are some of the useful options (see Event.pm for
where this is mostly from).

the problem with signal alarm is that it doesn't have any way to handle
the extra options without major pain.


callback code ref, closure, method (and object in diff
arg) or Signal::ALARM.
this could have a default like ::timer_handler

delay MINIMUM delay before timer gets triggered

at absolute time. converted internally to delay

interval repeat interval. if this is set and delay isn't,
the first delay will be this interval. this gets
you a simple repeating trigger.

hard this is useful boolean but can be tricky to explain. a
hard timer doesn't count the time used in the
callback. its intervals are hard (i.e. always 5
seconds). a soft timer counts the interval from
when the callback returns. so it is 5 seconds
plus callback time as the interval.

object callback to this object (forces the callback to
be method name).

Event.pm has a single callback arg, either a sub name or code ref or a
anon array with a method and object.

so the api could be as simple as this (p5ish style):

sub timer_handler {

say 'my time has come!'
}

set_timer_handler( interval => 5.0 ) ;

main_event_loop() ;

note the use of the default callback sub name.

a more complex one:


method timer_method {

say 'my time has come!'
}

set_timer_handler( callback => timer_method, object => $obj, interval => 5.0 ) ;

main_event_loop() ;


also the set_timer func returns a handle to manage the timer. then you
can reset it (reset the timer to 0 for this interval. useful for i/o
activity monitoring), disable/enable it and shut it down. so i would say
the returned thing should be an event object with those (and other)
methods. this implies a core Event class to handle this common stuff.

and integrating with other event loops (GUI ones in particular) is
handled by creating Event::EventLoopofChoice wrapper modules with the
same api as the core perl event class.

related topics include using events and continuations/coroutines instead
of callbacks. this means a yield type of func is needed (return is yeild
in typical event loops).

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Brent 'Dax' Royal-Gordon

unread,
Apr 21, 2005, 4:51:36 PM4/21/05
to perl6-l...@perl.org
Larry Wall <la...@wall.org> wrote:
> Assuming we
> rehuffmanize "kill" to "sendsignal" or some such, we have:

"signal" is a verb as well as a noun.

sub alarm ($secs) {
{ signal $*PID, Signal::ALARM }.cue(:delay($secs));
}

It even reads pretty nicely: "signal 4242".

--
Brent 'Dax' Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker

"I used to have a life, but I liked mail-reading so much better."

Larry Wall

unread,
Apr 21, 2005, 6:22:53 PM4/21/05
to perl6-l...@perl.org
On Thu, Apr 21, 2005 at 01:51:36PM -0700, Brent 'Dax' Royal-Gordon wrote:
: Larry Wall <la...@wall.org> wrote:
: > Assuming we
: > rehuffmanize "kill" to "sendsignal" or some such, we have:
:
: "signal" is a verb as well as a noun.
:
: sub alarm ($secs) {
: { signal $*PID, Signal::ALARM }.cue(:delay($secs));
: }
:
: It even reads pretty nicely: "signal 4242".

The cultural problem is that C's ancient signal() sets a signal
handler rather than sending a signal. I figured as long as we were
trying to discourage the use of signals we might as well make it
something even longer, but clearer.

Larry

Reply all
Reply to author
Forward
0 new messages