File Coverage

blib/lib/RxPerl/SyncTimers.pm
Criterion Covered Total %
statement 63 63 100.0
branch 8 10 80.0
condition 3 3 100.0
subroutine 15 15 100.0
pod 0 2 0.0
total 89 93 95.7


line stmt bran cond sub pod time code
1             package RxPerl::SyncTimers;
2              
3 4     4   21 use strict;
  4         5  
  4         89  
4 4     4   15 use warnings;
  4         8  
  4         83  
5              
6 4     4   1397 use parent 'RxPerl::Base';
  4         985  
  4         18  
7              
8 4     4   1722 use RxPerl ':all';
  4         12  
  4         1604  
9              
10 4     4   1544 use Sub::Util 'set_subname';
  4         1008  
  4         180  
11              
12 4     4   21 use Exporter 'import';
  4         7  
  4         2234  
13             our @EXPORT_OK = (@RxPerl::EXPORT_OK);
14             our %EXPORT_TAGS = (%RxPerl::EXPORT_TAGS);
15              
16             our $VERSION = "v6.27.1";
17              
18             foreach my $func_name (@EXPORT_OK) {
19             set_subname __PACKAGE__."::$func_name", \&{$func_name};
20             }
21              
22             our $promise_class;
23             our $DEBUG = 0;
24              
25             my $_id_cursor = 0;
26             my %_timed_events;
27             my %_timeline;
28              
29             our $time = 0;
30              
31             sub reset {
32 236     236 0 328 my ($class) = @_;
33              
34 236         268 $_id_cursor = 0;
35 236         364 undef %_timed_events;
36 236         289 undef %_timeline;
37 236         369 $time = 0;
38             }
39              
40             sub start {
41 240     240 0 391 my ($class) = @_;
42              
43 240         468 while (%_timeline) {
44 968         2519 my @times = sort {$a <=> $b} keys %_timeline;
  3255         4467  
45 968         1404 $time = $times[0];
46 968 50       1380 print "** Time jump to: $time **\n" if $DEBUG;
47 968         1048 while (my $item = shift @{ $_timeline{$time} }) {
  2666         5230  
48 1698         2950 delete $_timed_events{$item->{id}};
49 1698         2848 $item->{sub}->();
50             }
51 968         2281 delete $_timeline{$time};
52             }
53             }
54              
55 1799     1799   8125 sub _round_number { 0 + sprintf("%.1f", $_[0]) }
56              
57             sub _timer {
58 1799     1799   2845 my ($after, $sub, %opts) = @_;
59              
60             # opts can be: id
61              
62 1799   100     4275 my $id = $opts{id} // $_id_cursor++;
63 1799         2940 my $target_time = _round_number($time + $after);
64 1799         4766 $_timed_events{$id} = {
65             time => $target_time,
66             sub => $sub,
67             };
68 1799         2044 push @{ $_timeline{$target_time} }, {
  1799         5623  
69             id => $id,
70             sub => $sub,
71             };
72              
73 1799         4031 return $id;
74             }
75              
76             sub _cancel_timer {
77 281     281   391 my ($id) = @_;
78              
79 281 100       530 return if !defined $id;
80              
81 185 100       416 my $event = delete $_timed_events{$id} or return;
82              
83 101 50       377 exists $_timeline{$event->{time}} or return;
84              
85 101         150 @{ $_timeline{$event->{time}} } = grep {$_->{id} ne $id} @{ $_timeline{$event->{time}} };
  101         287  
  124         279  
  101         228  
86              
87 101 100       127 if (! @{ $_timeline{$event->{time}} }) {
  101         336  
88 83         547 delete $_timeline{$event->{time}};
89             }
90             }
91              
92             sub _add_recursive_timer {
93 242     242   322 my ($after, $sub, $id) = @_;
94              
95             _timer($after, sub {
96 191     191   361 _add_recursive_timer($after, $sub, $id);
97 191         332 $sub->();
98 242         673 }, id => $id);
99             }
100              
101             sub _interval {
102 51     51   80 my ($after, $sub) = @_;
103              
104 51         81 my $id = $_id_cursor++;
105              
106 51         113 _add_recursive_timer($after, $sub, $id);
107              
108 51         98 return $id;
109             }
110              
111             sub _cancel_interval {
112 147     147   208 my ($id) = @_;
113              
114 147         215 _cancel_timer($id);
115             }
116              
117             1;