File Coverage

blib/lib/Event.pm
Criterion Covered Total %
statement 119 127 93.7
branch 34 56 60.7
condition 1 3 33.3
subroutine 18 20 90.0
pod 3 6 50.0
total 175 212 82.5


line stmt bran cond sub pod time code
1 25     25   200079 use strict;
  25         253  
  25         1988  
2              
3             BEGIN { # do the right thing for threads?
4 25 50   25   86 eval { require attrs; } or do {
  25         4971  
5 25         98 $INC{'attrs.pm'} = "";
6 25     0   1209 *attrs::import = sub {};
7             }
8             }
9              
10             package Event;
11             require 5.008;
12 25     25   160 use base 'Exporter';
  25         47  
  25         3842  
13 25     25   188 use Carp;
  25         43  
  25         28110  
14             eval { require Carp::Heavy; }; # work around perl_call_pv bug XXX
15             our $API;
16             our $VERSION = '1.28';
17              
18             # If we inherit DynaLoader then we inherit AutoLoader; Bletch!
19             require DynaLoader;
20              
21             # DynaLoader calls dl_load_flags as a static method.
22             *dl_load_flags = DynaLoader->can('dl_load_flags');
23             (defined(&bootstrap)? \&bootstrap : \&DynaLoader::bootstrap)->
24             (__PACKAGE__, $VERSION);
25              
26             our $DebugLevel = 0;
27             our $Eval = 0; # avoid because c_callback is exempt
28             our $DIED = \&default_exception_handler;
29              
30             our @EXPORT_OK = qw(time all_events all_watchers all_running all_queued all_idle
31             one_event sweep loop unloop unloop_all sleep queue
32             queue_pending
33             QUEUES PRIO_NORMAL PRIO_HIGH NO_TIME_HIRES);
34              
35             sub import {
36 24     24   275 my $pkg = shift;
37 24         44 our $NO_TIME_HIRES;
38 24         45 my @sym;
39 24         65 for my $sym (@_) {
40 32 50       81 if ($sym eq 'NO_TIME_HIRES') {
41 0         0 $NO_TIME_HIRES = 1;
42             } else {
43 32         70 push @sym, $sym;
44             }
45             }
46              
47 24 50       79 if (!$NO_TIME_HIRES) {
48 24         39 eval { require Time::HiRes; };
  24         13638  
49 24 50       35226 if ($@ =~ /^Can\'t locate Time/) {
    50          
50             # OK, just continue
51             } elsif ($@) {
52 0 0       0 die if $@;
53             } else {
54 24         440 cache_time_api(); # hook in high precision time
55             }
56             }
57              
58 24         33944 $pkg->export_to_level(1, undef, @sym);
59             }
60              
61             # broadcast_adjust for Time::Warp? XXX
62              
63             sub _load_watcher {
64 125     125   220 my $sub = shift;
65 125         219 eval { require "Event/$sub.pm" };
  125         64653  
66 125 50       388 die if $@;
67 125 50       339 croak "Event/$sub.pm did not define Event::$sub\::new"
68             unless defined &$sub;
69 125         358 1;
70             }
71              
72             sub AUTOLOAD {
73 0     0   0 my $sub = ($Event::AUTOLOAD =~ /(\w+)$/)[0];
74 0 0       0 _load_watcher($sub) or croak $@ . ', Undefined subroutine &' . $sub;
75 0         0 carp "Autoloading with Event->$sub(...) is deprecated;
76             \tplease 'use Event::type qw($sub);' explicitly";
77 0         0 goto &$sub;
78             }
79              
80             sub default_exception_handler {
81 1     1 0 4 my ($run,$err) = @_;
82 1         3 my $desc = '?';
83 1         2 my $w;
84 1 50 33     40 if ($run and ($w = $run->w)) {
85 1         11 $desc = "`".$w->desc."'";
86             }
87 1         4 my $m = "Event: trapped error in $desc: $err";
88 1 50       14 $m .= "\n" if $m !~ m/\n$/;
89 1         10 warn $m;
90             #Carp::cluck "Event: fatal error trapped in '$desc'";
91             }
92              
93             sub verbose_exception_handler { #AUTOLOAD XXX
94 1     1 0 5 my ($e,$err) = @_;
95              
96 1         4 my $m = "Event: trapped error: $err";
97 1 50       8 $m .= "\n" if $m !~ m/\n$/;
98 1 50       10 return warn $m if !$e;
99              
100 1         5 my $w = $e->w;
101 1         8 $m .= " in $w --\n";
102              
103 1         12 for my $k ($w->attributes) {
104 11         28 $m .= sprintf "%18s: ", $k;
105 11         14 eval {
106 11         52 my $v = $w->$k();
107 11 100       96 if (!defined $v) {
    100          
108 1         2 $m .= '';
109             } elsif ($v =~ /^-?\d+(\.\d+)?$/) {
110 5         13 $m .= $v;
111             } else {
112 5         13 $m .= "'$v'";
113             }
114             };
115 11 50       29 if ($@) { $m .= "[$@]"; $@=''; }
  0         0  
  0         0  
116 11         16 $m .= "\n";
117             }
118 1         7 warn $m;
119             }
120              
121             sub sweep {
122 3 50   3 1 500730 my $prio = @_ ? shift : QUEUES();
123 3         29 queue_pending();
124 3         46 my $errsv = '';
125 3         31 while (1) {
126 5         13 eval { $@ = $errsv; _empty_queue($prio) };
  5         10  
  5         31  
127 5         548 $errsv = $@;
128 5 100       26 if ($@) {
129             # if ($Event::DebugLevel >= 2) {
130             # my $e = all_running();
131             # warn "Event: '$e->{desc}' died with: $@";
132             # }
133             next
134 2         4 }
135 3         152 last;
136             }
137             }
138              
139 25     25   237 use vars qw($Result $TopResult);
  25         62  
  25         1935  
140              
141             my $loop_timer;
142             sub loop {
143 25     25   14726 use integer;
  25         380  
  25         145  
144 117 100   117 1 13512 if (@_) {
145 2         5 my $how_long = shift;
146 2 100       10 if (!$loop_timer) {
147             $loop_timer = Event->timer(desc => "Event::loop timeout",
148             after => $how_long,
149 1     1   46 cb => sub { unloop($how_long) },
150 1         11 parked=>1);
151 1         5 $loop_timer->prio(PRIO_HIGH());
152             } else {
153 1         16 $loop_timer->at(Event::time() + $how_long),
154             }
155 2         13 $loop_timer->start;
156             }
157 117         186 $TopResult = undef; # allow re-entry of loop after unloop_all
158 117         186 local $Result = undef;
159 117         302 _incr_looplevel();
160 117         181 my $errsv = '';
161 117         195 while (1) {
162             # like G_EVAL | G_KEEPERR
163 121         252 eval { $@ = $errsv; _loop() };
  121         202  
  121         1878057  
164 121         6508077 $errsv = $@;
165 121 100       321 if ($@) {
166 4 50       17 warn "Event::loop caught: $@"
167             if $Event::DebugLevel >= 4;
168             next
169 4         10 }
170 117         177 last;
171             }
172 117         258 _decr_looplevel();
173 117 100       277 $loop_timer->stop if $loop_timer;
174 117         181 my $r = $Result;
175 117 100       226 $r = $TopResult if !defined $r;
176 117 0       232 warn "Event: unloop(".(defined $r?$r:'').")\n"
    50          
177             if $Event::DebugLevel >= 3;
178 117         781 $r
179             }
180              
181             sub add_hooks {
182 128 100   128 1 823 shift if @_ & 1; #?
183 128         448 while (@_) {
184 4         9 my $k = shift;
185 4         5 my $v = shift;
186 4 50       11 croak "$v must be CODE" if ref $v ne 'CODE';
187 4         17 _add_hook($k, $v);
188             }
189             }
190              
191 25     25   9890 END { $_->cancel for all_watchers() } # buggy? XXX
192              
193             package Event::Event::Io;
194 25     25   10416 use vars qw(@ISA);
  25         60  
  25         1904  
195             @ISA = 'Event::Event';
196              
197             package Event::Event::Dataful;
198 25     25   189 use vars qw(@ISA);
  25         67  
  25         5631  
199             @ISA = 'Event::Event';
200              
201             package Event;
202             require Event::Watcher;
203             _load_watcher($_) for qw(idle io signal timer var);
204              
205             # Provide hints to Inline.pm for usage:
206             # use Inline with => 'Event';
207             sub Inline {
208 3     3 0 856 my ($class, $language) = @_;
209 3         448 require Event::MakeMaker;
210 3         7 my $path = $Event::MakeMaker::installsitearch;
211 3         11 require Config;
212 3         20 my $so = $Config::Config{so};
213             return {
214 3         28 INC => "-I $path/Event",
215             TYPEMAPS => "$path/Event/typemap",
216             MYEXTLIB => "$path/auto/Event/Event.$so",
217             AUTO_INCLUDE => '#include "EventAPI.h"',
218             BOOT => 'I_EVENT_API("Inline");',
219             };
220             }
221              
222             1;