File Coverage

blib/lib/Event.pm
Criterion Covered Total %
statement 113 128 88.2
branch 34 58 58.6
condition 1 3 33.3
subroutine 17 20 85.0
pod 3 6 50.0
total 168 215 78.1


line stmt bran cond sub pod time code
1 24     24   116802 use strict;
  24         204  
  24         1711  
2              
3             BEGIN { # do the right thing for threads?
4 24 50   24   83 eval { require attrs; } or do {
  24         3591  
5 24         87 $INC{'attrs.pm'} = "";
6 24     0   1132 *attrs::import = sub {};
7             }
8             }
9              
10             package Event;
11             require 5.008;
12 24     24   142 use base 'Exporter';
  24         47  
  24         3126  
13 24     24   170 use Carp;
  24         61  
  24         24468  
14             eval { require Carp::Heavy; }; # work around perl_call_pv bug XXX
15             our $API;
16             our $VERSION = '1.27';
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   247 my $pkg = shift;
37 24         36 our $NO_TIME_HIRES;
38 24         43 my @sym;
39 24         55 for my $sym (@_) {
40 32 50       80 if ($sym eq 'NO_TIME_HIRES') {
41 0         0 $NO_TIME_HIRES = 1;
42             } else {
43 32         64 push @sym, $sym;
44             }
45             }
46              
47 24 50       74 if (!$NO_TIME_HIRES) {
48 24         41 eval { require Time::HiRes; };
  24         11828  
49 24 50       31009 if ($@ =~ /^Can\'t locate Time/) {
    50          
50             # OK, just continue
51             } elsif ($@) {
52 0 0       0 die if $@;
53             } else {
54 24         403 cache_time_api(); # hook in high precision time
55             }
56             }
57              
58 24         28795 $pkg->export_to_level(1, undef, @sym);
59             }
60              
61             # broadcast_adjust for Time::Warp? XXX
62              
63             sub _load_watcher {
64 120     120   201 my $sub = shift;
65 120         181 eval { require "Event/$sub.pm" };
  120         50131  
66 120 50       352 die if $@;
67 120 50       309 croak "Event/$sub.pm did not define Event::$sub\::new"
68             unless defined &$sub;
69 120         404 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         2 my $desc = '?';
83 1         2 my $w;
84 1 50 33     18 if ($run and ($w = $run->w)) {
85 1         6 $desc = "`".$w->desc."'";
86             }
87 1         3 my $m = "Event: trapped error in $desc: $err";
88 1 50       7 $m .= "\n" if $m !~ m/\n$/;
89 1         7 warn $m;
90             #Carp::cluck "Event: fatal error trapped in '$desc'";
91             }
92              
93             sub verbose_exception_handler { #AUTOLOAD XXX
94 1     1 0 4 my ($e,$err) = @_;
95              
96 1         3 my $m = "Event: trapped error: $err";
97 1 50       7 $m .= "\n" if $m !~ m/\n$/;
98 1 50       9 return warn $m if !$e;
99              
100 1         4 my $w = $e->w;
101 1         8 $m .= " in $w --\n";
102              
103 1         8 for my $k ($w->attributes) {
104 11         27 $m .= sprintf "%18s: ", $k;
105 11         14 eval {
106 11         62 my $v = $w->$k();
107 11 100       55 if (!defined $v) {
    100          
108 1         3 $m .= '';
109             } elsif ($v =~ /^-?\d+(\.\d+)?$/) {
110 5         13 $m .= $v;
111             } else {
112 5         19 $m .= "'$v'";
113             }
114             };
115 11 50       22 if ($@) { $m .= "[$@]"; $@=''; }
  0         0  
  0         0  
116 11         15 $m .= "\n";
117             }
118 1         7 warn $m;
119             }
120              
121             sub sweep {
122 3 50   3 1 500687 my $prio = @_ ? shift : QUEUES();
123 3         26 queue_pending();
124 3         44 my $errsv = '';
125 3         7 while (1) {
126 5         27 eval { $@ = $errsv; _empty_queue($prio) };
  5         10  
  5         49  
127 5         471 $errsv = $@;
128 5 100       24 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         131 last;
136             }
137             }
138              
139 24     24   193 use vars qw($Result $TopResult);
  24         64  
  24         1622  
140              
141             my $loop_timer;
142             sub loop {
143 24     24   11761 use integer;
  24         340  
  24         120  
144 117 100   117 1 13296 if (@_) {
145 2         4 my $how_long = shift;
146 2 100       7 if (!$loop_timer) {
147             $loop_timer = Event->timer(desc => "Event::loop timeout",
148             after => $how_long,
149 1     1   36 cb => sub { unloop($how_long) },
150 1         9 parked=>1);
151 1         5 $loop_timer->prio(PRIO_HIGH());
152             } else {
153 1         10 $loop_timer->at(Event::time() + $how_long),
154             }
155 2         9 $loop_timer->start;
156             }
157 117         159 $TopResult = undef; # allow re-entry of loop after unloop_all
158 117         172 local $Result = undef;
159 117         273 _incr_looplevel();
160 117         179 my $errsv = '';
161 117         175 while (1) {
162             # like G_EVAL | G_KEEPERR
163 121         255 eval { $@ = $errsv; _loop() };
  121         213  
  121         2078028  
164 121         6489775 $errsv = $@;
165 121 100       320 if ($@) {
166 4 50       14 warn "Event::loop caught: $@"
167             if $Event::DebugLevel >= 4;
168             next
169 4         9 }
170 117         165 last;
171             }
172 117         221 _decr_looplevel();
173 117 100       234 $loop_timer->stop if $loop_timer;
174 117         159 my $r = $Result;
175 117 100       255 $r = $TopResult if !defined $r;
176 117 0       235 warn "Event: unloop(".(defined $r?$r:'').")\n"
    50          
177             if $Event::DebugLevel >= 3;
178 117         696 $r
179             }
180              
181             sub add_hooks {
182 123 100   123 1 693 shift if @_ & 1; #?
183 123         441 while (@_) {
184 4         7 my $k = shift;
185 4         7 my $v = shift;
186 4 50       6 croak "$v must be CODE" if ref $v ne 'CODE';
187 4         15 _add_hook($k, $v);
188             }
189             }
190              
191 24     24   7726 END { $_->cancel for all_watchers() } # buggy? XXX
192              
193             package Event::Event::Io;
194 24     24   9588 use vars qw(@ISA);
  24         52  
  24         1737  
195             @ISA = 'Event::Event';
196              
197             package Event::Event::Dataful;
198 24     24   182 use vars qw(@ISA);
  24         60  
  24         5333  
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 0     0 0   my ($class, $language) = @_;
209 0 0         return if $language ne 'C'; # Inline gives good error message
210 0           require Event::MakeMaker;
211 0           my $path = $Event::MakeMaker::installsitearch;
212 0           require Config;
213 0           my $so = $Config::Config{so};
214             return {
215 0           INC => "-I $path/Event",
216             TYPEMAPS => "$path/Event/typemap",
217             MYEXTLIB => "$path/auto/Event/Event.$so",
218             AUTO_INCLUDE => '#include "EventAPI.h"',
219             BOOT => 'I_EVENT_API("Inline");',
220             };
221             }
222              
223             1;