1 /*
2 Copyright (C) 2008 Tomash Brechko. All rights reserved.
3
4 When used to build Perl module:
5
6 This library is free software; you can redistribute it and/or modify
7 it under the same terms as Perl itself, either Perl version 5.8.8
8 or, at your option, any later version of Perl 5 you may have
9 available.
10
11 When used as a standalone library:
12
13 This library is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as
15 published by the Free Software Foundation; either version 2.1 of the
16 License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22 */
23
24 #include "poll_select.h"
25 #ifndef WIN32
26 #include "socket_posix.h"
27 #else /* WIN32 */
28 #include "socket_win32.h"
29 #endif /* WIN32 */
30
31
32 int
poll_select(struct pollfd * fds,int nfds,int timeout)33 poll_select(struct pollfd *fds, int nfds, int timeout)
34 {
35 fd_set read_set, write_set, exception_set;
36 struct timeval to, *pto;
37 int max_fd = -1;
38 int select_res, poll_res;
39 int i;
40
41 if (timeout >= 0)
42 {
43 pto = &to;
44 pto->tv_sec = timeout / 1000;
45 pto->tv_usec = (timeout % 1000) * 1000;
46 }
47 else
48 {
49 pto = NULL;
50 }
51
52 FD_ZERO(&read_set);
53 FD_ZERO(&write_set);
54 FD_ZERO(&exception_set);
55
56 for (i = 0; i < nfds; ++i)
57 {
58 fds[i].revents = 0;
59
60 /* POSIX requires skipping fd less than zero. */
61 if (fds[i].fd < 0)
62 continue;
63
64 /*
65 To continue is the best we can do here, but we shouldn't be
66 called with non-select()'able descriptor at the first place.
67 */
68 if (! can_poll_fd(fds[i].fd))
69 continue;
70
71 if (max_fd < fds[i].fd)
72 max_fd = fds[i].fd;
73
74 if (fds[i].events & POLLIN)
75 FD_SET(fds[i].fd, &read_set);
76 if (fds[i].events & POLLOUT)
77 FD_SET(fds[i].fd, &write_set);
78 /*
79 poll() waits for error condition even when no other event is
80 requested (events == 0). POSIX says that pending socket error
81 should be an exceptional condition. However other exceptional
82 conditions are protocol-specific. For instance for TCP
83 out-of-band data is often also exceptional. So we enable
84 exceptions unconditionally, and callers should treat returned
85 POLLERR as "may read/write".
86 */
87 FD_SET(fds[i].fd, &exception_set);
88 }
89
90 select_res = select(max_fd + 1, &read_set, &write_set, &exception_set, pto);
91
92 if (select_res > 0)
93 {
94 /*
95 select() returns number of bits set, but poll() returns number
96 of flagged structures.
97 */
98 poll_res = 0;
99 for (i = 0; i < nfds; ++i)
100 {
101 if (FD_ISSET(fds[i].fd, &read_set))
102 {
103 fds[i].revents |= POLLIN;
104 --select_res;
105 }
106 if (FD_ISSET(fds[i].fd, &write_set))
107 {
108 fds[i].revents |= POLLOUT;
109 --select_res;
110 }
111 if (FD_ISSET(fds[i].fd, &exception_set))
112 {
113 fds[i].revents |= POLLERR;
114 --select_res;
115 }
116
117 if (fds[i].revents != 0)
118 {
119 ++poll_res;
120
121 if (select_res == 0)
122 break;
123 }
124 }
125 }
126 else
127 {
128 poll_res = select_res;
129 }
130
131 return poll_res;
132 }
133