IO::As...untdown(3pm)
π NAME π
okay so bestie, say hi to IO::Async::Timer::Countdown β it's the one that fires your event callback after a fixed delay β³β¨
πΈ SYNOPSIS πΈ
use IO::Async::Timer::Countdown;
use IO::Async::Loop;
my $loop = IO::Async::Loop->new;
my $timer = IO::Async::Timer::Countdown->new(
delay => 10,
on_expire => sub {
print "Sorry, your time's up\n";
$loop->stop;
},
);
$timer->start;
$loop->add( $timer );
$loop->run;
π¦ DESCRIPTION π¦
So this is a subclass of IO::Async::Timer, and what it does is one-shot fixed delays, periodt. The object is lowkey a countdown timer: it calls its callback after the given period, counted from whenever you started it. Once it's expired the Timer can be started again, and then it'll wait the exact same period and hit the callback again. And if a timer is currently running, you can stop it or reset it β no drama π
ngl if you wanted a "Timer" object that just keeps running a callback at regular intervals, you want IO::Async::Timer::Periodic instead. And if you want a "Timer" that fires at a fixed time in the future, that's IO::Async::Timer::Absolute. Pick your icon π
π₯ EVENTS π₯
These events get invoked β either using subclass methods, or CODE references in parameters:
β¨ on_expire β¨
Invoked when the timer expires. That's it, that's the event π«Ά
π PARAMETERS π
These named parameters can be passed to "new" or "configure":
π on_expire => CODE
CODE reference for the "on_expire" event.
π delay => NUM
The delay in seconds after starting the timer until it expires. Heads up: this cannot be changed if the timer is running. And a timer with a zero delay expires "immediately" π
π remove_on_expire => BOOL
Optional. If true, this timer object removes itself from its parent notifier or containing loop when it expires. Defaults to false.
Once constructed, the timer object will need to be added to the "Loop" before it will work. It'll also need to be started by the "start" method. (No, it won't just β¨manifestβ¨ on its own, bestie.)
π METHODS π
π is_expired
$expired = $timer->is_expired;
Returns true if the Timer has already expired. Simple as π§
π« reset
$timer->reset;
If the timer is running, restart the countdown period from now. If the timer is not running, this method has no effect β it's giving "just vibes, nothing happens" π
β EXAMPLES β
πΆ Watchdog Timer πΆ
Because the "reset" method restarts a running countdown timer back to its full period, it can be used to implement a watchdog timer. That's a timer which will not expire provided the method is called at least as often as it is configured. If the method fails to be called, the timer will eventually expire and run its callback. It's giving "you had ONE job" π
For example, to expire an accepted connection after 30 seconds of inactivity:
...
on_accept => sub {
my ( $newclient ) = @_;
my $watchdog = IO::Async::Timer::Countdown->new(
delay => 30,
on_expire => sub {
my $self = shift;
my $stream = $self->parent;
$stream->close;
},
);
my $stream = IO::Async::Stream->new(
handle => $newclient,
on_read => sub {
my ( $self, $buffref, $eof ) = @_;
$watchdog->reset;
...
},
on_closed => sub {
$watchdog->stop;
},
) );
$stream->add_child( $watchdog );
$watchdog->start;
$loop->add( $watchdog );
}
Rather than setting up a lexical variable to store the Stream so that the Timer's "on_expire" closure can call "close" on it, the parent/child relationship between the two Notifier objects is used. At the time the Timer "on_expire" closure is invoked, it will have been added as a child notifier of the Stream β which means the Timer's "parent" method will return the Stream Notifier. This lets it call "close" without needing to capture a lexical variable, which would create a cyclic reference. (iykyk, we do not do memory leaks in this house π«π)
π Fixed-Delay Repeating Timer π
The "on_expire" event fires a fixed delay after the "start" method has begun the countdown. The "start" method can be invoked again at some point during the "on_expire" handling code, to create a timer that invokes its code regularly a fixed delay after the previous invocation has finished. This creates an arrangement similar to an IO::Async::Timer::Periodic, except that it will wait until the previous invocation has indicated it is finished, before starting the countdown for the next call. So polite, so well-behaved π₯Ή
my $timer = IO::Async::Timer::Countdown->new(
delay => 60,
on_expire => sub {
my $self = shift;
start_some_operation(
on_complete => sub { $self->start },
);
},
);
$timer->start;
$loop->add( $timer );
This example invokes the "start_some_operation" function 60 seconds after the previous iteration has indicated it has finished. Chef's kiss π₯
π AUTHOR π
Paul Evans <leonerd@leonerd.org.uk> β absolute legend, no cap π«Ά
and that's the whole page bestie, you ate π
this was perl v5.40.1, dated 2026-02-21, from the User Contributed Perl Documentation, filed under IO::As...untdown(3pm) β slay, go forth and count down πβ¨π
π¦ where this page comes from
- ubuntu stonking: libio-async-perl 0.805-1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms