Data-HierTimingWheel-Shared
view release on metacpan or search on metacpan
eg/cross_process.pl view on Meta::CPAN
#!/usr/bin/env perl
# Cross-process: parent builds a hierarchical timing wheel via memfd, children
# each schedule their own timers (at widely varying horizons) into the one shared
# wheel, and the parent owns advancing the clock and dispatching whatever fires
# -- the producer/consumer split a shared timer service naturally allows.
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../blib/lib", "$FindBin::Bin/../blib/arch";
use POSIX qw(_exit);
use Data::HierTimingWheel::Shared;
$| = 1;
my $kids = 4;
my $per = 2000;
my $cap = $kids * $per + 16;
# 256 slots x 4 levels -> delays up to 256**4 - 1 (~4.3 billion ticks)
my $tw = Data::HierTimingWheel::Shared->new_memfd('hiertimingwheel-demo', 256, 4, $cap);
my $fd = $tw->memfd;
printf "parent: created wheel (%d slots x %d levels, capacity %d) via memfd fd=%d\n",
$tw->num_slots, $tw->num_levels, $tw->capacity, $fd;
my @pids;
for my $c (0 .. $kids - 1) {
my $pid = fork // die "fork: $!";
if ($pid == 0) {
my $child = Data::HierTimingWheel::Shared->new_from_fd($fd);
my $seed = 1 + $c;
for my $i (1 .. $per) {
$seed = ($seed * 1103515245 + 12345) & 0x7fffffff;
my $delay = 1 + $seed % 5000; # 1..5000 ticks (spans 2 levels)
$child->add($delay, $c * $per + $i); # globally unique payload
}
_exit(0);
}
push @pids, $pid;
}
waitpid $_, 0 for @pids;
printf "parent: %d timers scheduled by %d children\n\n", $tw->count, $kids;
# advance the clock past every delay and count how many fire
my $total_fired = 0;
$total_fired += scalar $tw->advance(1) for 1 .. 5000;
printf "after 5000 ticks: %d timers fired, %d still pending\n", $total_fired, $tw->count;
printf "(every delay was in 1..5000, so all should have fired -- through 2 levels of cascades)\n";
( run in 0.622 second using v1.01-cache-2.11-cpan-e7c6538aa59 )