File Coverage

blib/lib/Loop/Sustainable.pm
Criterion Covered Total %
statement 18 53 33.9
branch 0 12 0.0
condition 0 2 0.0
subroutine 6 8 75.0
pod 1 1 100.0
total 25 76 32.8


line stmt bran cond sub pod time code
1             package Loop::Sustainable;
2              
3 1     1   5 use strict;
  1         1  
  1         34  
4 1     1   4 use warnings;
  1         1  
  1         26  
5              
6 1     1   4 use Carp;
  1         2  
  1         77  
7 1     1   4 use Exporter qw(import);
  1         2  
  1         29  
8 1     1   1063 use Class::Load qw(load_class);
  1         38676  
  1         67  
9 1     1   1396 use Time::HiRes qw(tv_interval gettimeofday);
  1         2076  
  1         5  
10              
11             our $VERSION = '0.02';
12             our @EXPORT = qw(loop_sustainable);
13              
14             sub loop_sustainable (&&;$) {
15 0     0 1   my ( $cb, $terminator, $args ) = @_;
16              
17 0   0       $args ||= +{};
18 0           %$args = (
19             wait_interval => 0.1,
20             check_strategy_interval => 10,
21             strategy => +{
22             class => 'ByLoad',
23             args => +{ load => 0.5 },
24             },
25             %$args,
26             );
27              
28 0           my $strategy_cb;
29              
30 0 0         if ( ref $args->{strategy} eq 'HASH' ) {
    0          
31 0 0         my ( $strategy_class ) = index($args->{strategy}{class}, '+') == 1 ?
32             substr($args->{strategy}{class}, 1) : 'Loop::Sustainable::Strategy::' . $args->{strategy}{class};
33              
34 0           load_class( $strategy_class );
35              
36 0           my $strategy = $strategy_class->new(
37             check_strategy_interval => $args->{check_strategy_interval},
38 0           %{$args->{strategy}{args}}
39             );
40              
41             $strategy_cb = sub {
42 0     0     my ( $execute_count, $time_sum, $rv ) = @_;
43 0           $strategy->wait_correction( $execute_count, $time_sum, $rv );
44 0           };
45             }
46             elsif ( ref $args->{strategy} eq 'CODE' ) {
47 0           $strategy_cb = $args->{strategy};
48             }
49             else {
50 0           croak 'Not supported strategy type. The strategy field must be hash reference or code reference.';
51             }
52              
53 0           my $i = 1;
54 0           my $time_sum = 0;
55 0           my $time_total = 0;
56 0           my $wait_interval = $args->{wait_interval};
57 0           my $additional_wait = 0;
58              
59 0           for (;;) {
60 0           my $t0 = [ Time::HiRes::gettimeofday ];
61 0           my @ret = $cb->( $i, $wait_interval );
62 0           my $elapsed = Time::HiRes::tv_interval( $t0, [ Time::HiRes::gettimeofday ] );
63              
64 0           $time_sum += $elapsed;
65 0           $time_total += $elapsed;
66              
67 0 0         if ( $terminator->( $i, $time_sum, \@ret ) ) {
68 0           last;
69             }
70              
71 0           Time::HiRes::sleep($wait_interval);
72              
73 0 0         if ( $i % $args->{check_strategy_interval} == 0 ) {
74 0           $additional_wait = $strategy_cb->( $i, $time_sum, \@ret );
75 0           $wait_interval = $args->{wait_interval} + $additional_wait;
76 0           $time_sum = 0;
77             }
78              
79 0           $i++;
80             }
81              
82 0           my %result = (
83             executed => $i,
84             total_time => $time_total
85             );
86              
87 0 0         return wantarray ? %result : \%result;
88             }
89              
90             1;
91             __END__