[xbuild] Microsoft.Common.targets - import Before/After targets files.
[mono.git] / support / fakepoll.h
1 // fakepoll.h
2 // poll using select
3 // Warning: a call to this poll() takes about 4K of stack space.
4
5 // Greg Parker     gparker-web@sealiesoftware.com     December 2000
6 // This code is in the public domain and may be copied or modified without 
7 // permission. 
8
9 // Updated May 2002: 
10 // * fix crash when an fd is less than 0
11 // * set errno=EINVAL if an fd is greater or equal to FD_SETSIZE
12 // * don't set POLLIN or POLLOUT in revents if it wasn't requested 
13 //   in events (only happens when an fd is in the poll set twice)
14
15 #ifndef _FAKE_POLL_H
16 #define _FAKE_POLL_H
17
18 #include <limits.h>
19 #define FD_SETSIZE OPEN_MAX
20 #include <sys/types.h>
21 #include <sys/time.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24
25 typedef struct pollfd {
26     int fd;                         /* file desc to poll */
27     short events;                   /* events of interest on fd */
28     short revents;                  /* events that occurred on fd */
29 } pollfd_t;
30
31
32 // poll flags
33 #define POLLIN  0x0001
34 #define POLLOUT 0x0004
35 #define POLLERR 0x0008
36
37 // synonyms
38 #define POLLNORM POLLIN
39 #define POLLPRI POLLIN
40 #define POLLRDNORM POLLIN
41 #define POLLRDBAND POLLIN
42 #define POLLWRNORM POLLOUT
43 #define POLLWRBAND POLLOUT
44
45 // ignored
46 #define POLLHUP 0x0010
47 #define POLLNVAL 0x0020
48
49 static
50 inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
51 {
52     struct timeval tv;
53     struct timeval *tvp;
54     fd_set readFDs, writeFDs, exceptFDs;
55     fd_set *readp, *writep, *exceptp;
56     struct pollfd *pollEnd, *p;
57     int selected;
58     int result;
59     int maxFD;
60
61     if (!pollSet) {
62         pollEnd = NULL;
63         readp = NULL;
64         writep = NULL;
65         exceptp = NULL;
66         maxFD = 0;
67     } 
68     else {
69         pollEnd = pollSet + pollCount;
70         readp = &readFDs;
71         writep = &writeFDs;
72         exceptp = &exceptFDs;
73
74         FD_ZERO(readp);
75         FD_ZERO(writep);
76         FD_ZERO(exceptp);
77         
78         // Find the biggest fd in the poll set
79         maxFD = 0;
80         for (p = pollSet; p < pollEnd; p++) {
81             if (p->fd > maxFD) maxFD = p->fd;
82         }
83
84         if (maxFD >= FD_SETSIZE) {
85             // At least one fd is too big
86             errno = EINVAL;
87             return -1;
88         }
89         
90         // Transcribe flags from the poll set to the fd sets
91         for (p = pollSet; p < pollEnd; p++) {
92             if (p->fd < 0) {
93                 // Negative fd checks nothing and always reports zero
94             } else {
95                 if (p->events & POLLIN)  FD_SET(p->fd, readp);
96                 if (p->events & POLLOUT) FD_SET(p->fd, writep);
97                 if (p->events != 0)      FD_SET(p->fd, exceptp);
98                 // POLLERR is never set coming in; poll() always reports errors
99                 // But don't report if we're not listening to anything at all.
100             }
101         }
102     }
103         
104     // poll timeout is in milliseconds. Convert to struct timeval.
105     // poll timeout == -1 : wait forever : select timeout of NULL
106     // poll timeout == 0  : return immediately : select timeout of zero
107     if (pollTimeout >= 0) {
108         tv.tv_sec = pollTimeout / 1000;
109         tv.tv_usec = (pollTimeout % 1000) * 1000;
110         tvp = &tv;
111     } else {
112         tvp = NULL;
113     }
114     
115     
116     selected = select(maxFD+1, readp, writep, exceptp, tvp);
117
118
119     if (selected < 0) {
120         // Error during select
121         result = -1;
122     } 
123     else if (selected > 0) {
124         // Select found something
125         // Transcribe result from fd sets to poll set.
126         // Also count the number of selected fds. poll returns the 
127         // number of ready fds; select returns the number of bits set.
128         int polled = 0;
129         for (p = pollSet; p < pollEnd; p++) {
130             p->revents = 0;
131             if (p->fd < 0) {
132                 // Negative fd always reports zero
133             } else {
134                 if ((p->events & POLLIN)   &&  FD_ISSET(p->fd, readp)) {
135                     p->revents |= POLLIN;
136                 }
137                 if ((p->events & POLLOUT)  &&  FD_ISSET(p->fd, writep)) {
138                     p->revents |= POLLOUT;
139                 }
140                 if ((p->events != 0)       &&  FD_ISSET(p->fd, exceptp)) {
141                     p->revents |= POLLERR;
142                 }
143
144                 if (p->revents) polled++;
145             }
146         }
147         result = polled;
148     }
149     else {
150         // selected == 0, select timed out before anything happened
151         // Clear all result bits and return zero.
152         for (p = pollSet; p < pollEnd; p++) {
153             p->revents = 0;
154         }
155         result = 0;
156     }
157
158     return result;
159 }
160
161
162 #endif