2010-06-17 Zoltan Varga <vargaz@gmail.com>
[mono.git] / support / fakepoll.h
blobb5805ee9f10b2824d984cf7d23cf07c8094d6d29
1 // fakepoll.h
2 // poll using select
3 // Warning: a call to this poll() takes about 4K of stack space.
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.
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)
15 #ifndef _FAKE_POLL_H
16 #define _FAKE_POLL_H
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>
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;
32 // poll flags
33 #define POLLIN 0x0001
34 #define POLLOUT 0x0004
35 #define POLLERR 0x0008
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
45 // ignored
46 #define POLLHUP 0x0010
47 #define POLLNVAL 0x0020
49 static
50 inline int poll(struct pollfd *pollSet, int pollCount, int pollTimeout)
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;
61 if (!pollSet) {
62 pollEnd = NULL;
63 readp = NULL;
64 writep = NULL;
65 exceptp = NULL;
66 maxFD = 0;
68 else {
69 pollEnd = pollSet + pollCount;
70 readp = &readFDs;
71 writep = &writeFDs;
72 exceptp = &exceptFDs;
74 FD_ZERO(readp);
75 FD_ZERO(writep);
76 FD_ZERO(exceptp);
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;
84 if (maxFD >= FD_SETSIZE) {
85 // At least one fd is too big
86 errno = EINVAL;
87 return -1;
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.
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;
116 selected = select(maxFD+1, readp, writep, exceptp, tvp);
119 if (selected < 0) {
120 // Error during select
121 result = -1;
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;
137 if ((p->events & POLLOUT) && FD_ISSET(p->fd, writep)) {
138 p->revents |= POLLOUT;
140 if ((p->events != 0) && FD_ISSET(p->fd, exceptp)) {
141 p->revents |= POLLERR;
144 if (p->revents) polled++;
147 result = polled;
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;
155 result = 0;
158 return result;
162 #endif