File Coverage

blib/lib/Hypersonic/Event/Poll.pm
Criterion Covered Total %
statement 28 30 93.3
branch n/a
condition n/a
subroutine 16 17 94.1
pod 12 13 92.3
total 56 60 93.3


line stmt bran cond sub pod time code
1             package Hypersonic::Event::Poll;
2              
3 3     3   239072 use strict;
  3         8  
  3         87  
4 3     3   10 use warnings;
  3         3  
  3         114  
5 3     3   38 use 5.010;
  3         8  
6              
7 3     3   9 use parent 'Hypersonic::Event::Role';
  3         4  
  3         19  
8              
9             our $VERSION = '0.15';
10              
11 2     2 1 1246 sub name { 'poll' }
12              
13             sub available {
14             # poll() is POSIX - available on all Unix systems
15             # Not available on Windows (use select instead)
16 7     7 1 1461 return $^O ne 'MSWin32';
17             }
18              
19             sub includes {
20 1     1 1 1027 return '#include ';
21             }
22              
23             sub defines {
24 1     1 1 1106 return <<'C';
25             #define EV_BACKEND_POLL 1
26             #ifndef MAX_EVENTS
27             #define MAX_EVENTS 1024
28             #endif
29             #ifndef MAX_POLL_FDS
30             #define MAX_POLL_FDS 10000
31             #endif
32             C
33             }
34              
35 1     1 1 1056 sub event_struct { 'pollfd' }
36              
37 1     1 1 1012 sub extra_cflags { '' }
38 1     1 1 3 sub extra_ldflags { '' }
39              
40             # poll() needs additional state tracking
41             sub gen_create {
42 1     1 1 1074 my ($class, $builder, $listen_fd_var) = @_;
43              
44 1         3 $builder->comment('poll() backend - allocate pollfd array')
45             ->line('static struct pollfd poll_fds[MAX_POLL_FDS];')
46             ->line('static int poll_nfds = 0;')
47             ->blank
48             ->line("poll_fds[0].fd = $listen_fd_var;")
49             ->line('poll_fds[0].events = POLLIN;')
50             ->line('poll_nfds = 1;')
51             ->line('int ev_fd = 0;') # Dummy - poll doesn't use event fd
52             ->blank;
53             }
54              
55             # Add fd to poll array
56             sub gen_add {
57 1     1 1 1340 my ($class, $builder, $loop_var, $fd_var) = @_;
58              
59 1         4 $builder->if('poll_nfds < MAX_POLL_FDS')
60             ->line("poll_fds[poll_nfds].fd = $fd_var;")
61             ->line('poll_fds[poll_nfds].events = POLLIN;')
62             ->line('poll_nfds++;')
63             ->endif;
64             }
65              
66             # Remove fd from poll array (compact)
67             sub gen_del {
68 1     1 1 970 my ($class, $builder, $loop_var, $fd_var) = @_;
69              
70 1         5 $builder->comment('Find and remove fd from poll array')
71             ->line('{ int j;')
72             ->line('for (j = 0; j < poll_nfds; j++) {')
73             ->line(" if (poll_fds[j].fd == $fd_var) {")
74             ->line(' poll_fds[j] = poll_fds[poll_nfds - 1];')
75             ->line(' poll_nfds--;')
76             ->line(' break;')
77             ->line(' }')
78             ->line('} }');
79             }
80              
81             # Wait using poll()
82             sub gen_wait {
83 2     2 1 1548 my ($class, $builder, $loop_var, $events_var, $count_var, $timeout_var) = @_;
84              
85             # poll() modifies the array in-place, doesn't need separate events array
86 2         17 $builder->line("int poll_result = poll(poll_fds, poll_nfds, $timeout_var);")
87             ->if('poll_result < 0')
88             ->if('errno == EINTR')
89             ->line('continue;')
90             ->endif
91             ->line('perror("poll");')
92             ->line('break;')
93             ->endif
94             ->line("int $count_var = poll_nfds;") # We check all fds
95             ->line("(void)$events_var;"); # Unused - we use poll_fds directly
96             }
97              
98             # poll() iteration is different - check revents
99             sub gen_get_fd {
100 1     1 1 1089 my ($class, $builder, $events_var, $index_var, $fd_var) = @_;
101              
102 1         6 $builder->comment('Check if this fd has events')
103             ->if("!(poll_fds[$index_var].revents & POLLIN)")
104             ->line('continue;') # Skip fds without events
105             ->endif
106             ->line("int $fd_var = poll_fds[$index_var].fd;");
107             }
108              
109             # Future/Pool integration - add pool notify fd to poll array
110             sub gen_add_pool_notify {
111 0     0 0   my ($class, $builder, $loop_var, $notify_fd_var) = @_;
112              
113 0           $builder->line("/* Add pool notify fd to poll array */")
114             ->if('poll_nfds < MAX_POLL_FDS')
115             ->line("poll_fds[poll_nfds].fd = $notify_fd_var;")
116             ->line('poll_fds[poll_nfds].events = POLLIN;')
117             ->line('poll_nfds++;')
118             ->endif;
119             }
120              
121             1;
122              
123             __END__