File Coverage

blib/lib/Stem/Event/Perl.pm
Criterion Covered Total %
statement 58 64 90.6
branch 13 18 72.2
condition 7 14 50.0
subroutine 10 11 90.9
pod 0 4 0.0
total 88 111 79.2


line stmt bran cond sub pod time code
1             # File: Stem/Event/Perl.pm
2              
3             # This file is part of Stem.
4             # Copyright (C) 1999, 2000, 2001 Stem Systems, Inc.
5              
6             # Stem is free software; you can redistribute it and/or modify
7             # it under the terms of the GNU General Public License as published by
8             # the Free Software Foundation; either version 2 of the License, or
9             # (at your option) any later version.
10              
11             # Stem is distributed in the hope that it will be useful,
12             # but WITHOUT ANY WARRANTY; without even the implied warranty of
13             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14             # GNU General Public License for more details.
15              
16             # You should have received a copy of the GNU General Public License
17             # along with Stem; if not, write to the Free Software
18             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19              
20             # For a license to use the Stem under conditions other than those
21             # described here, to purchase support for this software, or to purchase a
22             # commercial warranty contract, please contact Stem Systems at:
23              
24             # Stem Systems, Inc. 781-643-7504
25             # 79 Everett St. info@stemsystems.com
26             # Arlington, MA 02474
27             # USA
28              
29             =head1 Stem::Event::Perl
30              
31             This module is a pure Perl event loop. It requires Perl 5.8 (or
32             better) which has safe signal handling. It provides the common event
33             API for the standard classes:
34              
35             =cut
36              
37             package Stem::Event::Perl ;
38              
39 4     4   22 use strict ;
  4         8  
  4         136  
40 4     4   2037 use Stem::Event::Signal ;
  4         12  
  4         409  
41              
42             @Stem::Event::Perl::ISA = qw( Stem::Event ) ;
43              
44             BEGIN {
45              
46 4 50   4   9 unless ( eval { require Time::HiRes } ) {
  4         3708  
47              
48 0         0 Time::HiRes->import( qw( time ) ) ;
49             }
50             }
51              
52             # get the hashes for each of the event types
53              
54             my ( $signal_events, $timer_events, $read_events, $write_events ) =
55             map scalar( Stem::Event::_get_events( $_ )), qw( signal timer
56             read write ) ;
57              
58             sub _start_loop {
59              
60             #print "PERL START\n" ;
61              
62 3   66 3   126 while( keys %{$timer_events} ||
  10   66     56  
  3   33     17  
63 3         22 keys %{$signal_events} ||
64 3         18 keys %{$read_events} ||
65             keys %{$write_events} ) {
66              
67 7         25 my $timeout = find_min_delay() ;
68              
69             #print "TIMEOUT [$timeout]\n" ;
70              
71 7         10 my $time = time() ;
72              
73 7         19 _one_time_loop( $timeout ) ;
74              
75 7         22 my $delta_time = time() - $time ;
76 7         25 trigger_timer_events( $delta_time ) ;
77             }
78             }
79              
80             sub _one_time_loop {
81              
82 7     7   20 my( $timeout ) = @_ ;
83              
84             # force a no wait select call if no timeout was passed in
85              
86 7   50     22 $timeout ||= 0 ;
87              
88             #print "ONE TIME $timeout\n" ;
89             # use Carp qw( cluck ) ;
90             # cluck ;
91              
92             # print "\n\n********EVENT LOOP\n\n" ;
93             # print "READ EVENTS\n", map $_->dump(), values %{$read_events} ;
94             # print "WRITE EVENTS\n", map $_->dump(), values %{$write_events} ;
95              
96 7         24 my $read_vec = make_select_vec( $read_events ) ;
97 7         16 my $write_vec = make_select_vec( $write_events ) ;
98              
99             #print "R BEFORE ", unpack( 'b*', $read_vec), "\n" ;
100             #print "W BEFORE ", unpack( 'b*', $write_vec), "\n" ;
101              
102              
103 7         19012503 my $cnt = select( $read_vec, $write_vec, undef, $timeout ) ;
104              
105             #print "SEL CNT [$cnt]\n" ;
106             #print "R AFTER ", unpack( 'b*', $read_vec), "\n" ;
107             #print "W AFTER ", unpack( 'b*', $write_vec), "\n" ;
108              
109 7         58 trigger_select_vec( 'read', $read_events, $read_vec ) ;
110 7         23 trigger_select_vec( 'write', $write_events, $write_vec, ) ;
111              
112             #print "\n\n********END EVENT LOOP\n\n" ;
113              
114             }
115              
116             sub _stop_loop {
117              
118 3     3   7 $_->cancel() for values %{$signal_events},
  3         9  
  3         7  
119 3         6 values %{$timer_events},
120 3         25 values %{$read_events},
121             values %{$write_events} ;
122             }
123              
124             sub find_min_delay {
125              
126 7     7 0 11 my $min_delay = 0 ;
127              
128 7         16 while( my( undef, $event ) = each %{$timer_events} ) {
  14         54  
129              
130 7 50 33     54 if ( $event->{'time_left'} < $min_delay || $min_delay == 0 ) {
131              
132 7         17 $min_delay = $event->{'time_left'} ;
133              
134             #print "MIN [$min_delay]\n" ;
135             }
136             }
137              
138 7 50       21 return unless $min_delay ;
139              
140 7         16 return $min_delay ;
141             }
142              
143             sub trigger_timer_events {
144              
145 7     7 0 12 my( $delta ) = @_ ;
146              
147             #print "TIMER DELTA $delta\n" ;
148              
149 7         15 while( my( undef, $event ) = each %{$timer_events} ) {
  13         67  
150              
151             #print $event->dump() ;
152              
153 6 50       28 next unless $event->{'active'} ;
154              
155 6 100       27 next unless ( $event->{'time_left'} -= $delta ) <= 0 ;
156              
157 5         49 $event->timer_triggered() ;
158             }
159             }
160              
161             sub make_select_vec {
162              
163 14     14 0 22 my( $io_events ) = @_ ;
164              
165 14         23 my $select_vec = '' ;
166              
167 14         22 while( my( undef, $event ) = each %{$io_events} ) {
  24         78  
168              
169             #print "make F: [", fileno $event->{'fh'}, "] ACT [$event->{'active'}]\n" ;
170              
171 10 50       40 unless ( defined fileno $event->{'fh'} ) {
172              
173             #print "BAD FH $event->{'fh'}\n" ;
174 0         0 print "\n\n***EVENT BAD FH\n", $event->dump() ;
175              
176 0         0 $event->cancel() ;
177             }
178              
179 10 100       24 next unless $event->{'active'} ;
180 9         35 vec( $select_vec, fileno $event->{'fh'}, 1 ) = 1 ;
181             }
182              
183 14         38 return $select_vec ;
184             }
185              
186             sub trigger_select_vec {
187              
188 14     14 0 124 my( $event_type, $io_events, $select_vec ) = @_ ;
189              
190 14         29 while( my( undef, $event ) = each %{$io_events} ) {
  24         98  
191              
192 10 100       35 next unless $event->{'active'} ;
193 9 100       46 if ( vec( $select_vec, fileno $event->{'fh'}, 1 ) ) {
194              
195 2         10 $event->trigger() ;
196             }
197             }
198              
199 14         38 return ;
200             }
201              
202             ############################################################################
203              
204             package Stem::Event::Plain ;
205              
206             ######
207             # right now we trigger plain events when they are created. this should
208             # change to a queue and trigger after i/o and timer events
209             ######
210              
211             sub _build {
212 0     0     my( $self ) = @_ ;
213 0           $self->trigger() ;
214 0           return ;
215             }
216              
217             1 ;