cool.io 1.4.1-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGES.md +229 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +20 -0
  8. data/README.md +166 -0
  9. data/Rakefile +79 -0
  10. data/cool.io.gemspec +29 -0
  11. data/examples/callbacked_echo_server.rb +24 -0
  12. data/examples/dslified_echo_client.rb +34 -0
  13. data/examples/dslified_echo_server.rb +24 -0
  14. data/examples/echo_client.rb +38 -0
  15. data/examples/echo_server.rb +27 -0
  16. data/examples/google.rb +9 -0
  17. data/ext/cool.io/.gitignore +5 -0
  18. data/ext/cool.io/cool.io.h +59 -0
  19. data/ext/cool.io/cool.io_ext.c +25 -0
  20. data/ext/cool.io/ev_wrap.h +10 -0
  21. data/ext/cool.io/extconf.rb +61 -0
  22. data/ext/cool.io/iowatcher.c +189 -0
  23. data/ext/cool.io/libev.c +8 -0
  24. data/ext/cool.io/loop.c +261 -0
  25. data/ext/cool.io/stat_watcher.c +269 -0
  26. data/ext/cool.io/timer_watcher.c +219 -0
  27. data/ext/cool.io/utils.c +122 -0
  28. data/ext/cool.io/watcher.c +264 -0
  29. data/ext/cool.io/watcher.h +71 -0
  30. data/ext/iobuffer/extconf.rb +9 -0
  31. data/ext/iobuffer/iobuffer.c +767 -0
  32. data/ext/libev/Changes +507 -0
  33. data/ext/libev/LICENSE +37 -0
  34. data/ext/libev/README +58 -0
  35. data/ext/libev/README.embed +3 -0
  36. data/ext/libev/ev.c +5054 -0
  37. data/ext/libev/ev.h +853 -0
  38. data/ext/libev/ev_epoll.c +282 -0
  39. data/ext/libev/ev_kqueue.c +214 -0
  40. data/ext/libev/ev_poll.c +148 -0
  41. data/ext/libev/ev_port.c +185 -0
  42. data/ext/libev/ev_select.c +362 -0
  43. data/ext/libev/ev_vars.h +204 -0
  44. data/ext/libev/ev_win32.c +163 -0
  45. data/ext/libev/ev_wrap.h +200 -0
  46. data/ext/libev/ruby_gil.patch +97 -0
  47. data/ext/libev/test_libev_win32.c +123 -0
  48. data/ext/libev/win_select.patch +115 -0
  49. data/lib/.gitignore +2 -0
  50. data/lib/cool.io.rb +34 -0
  51. data/lib/cool.io/async_watcher.rb +43 -0
  52. data/lib/cool.io/custom_require.rb +9 -0
  53. data/lib/cool.io/dns_resolver.rb +219 -0
  54. data/lib/cool.io/dsl.rb +139 -0
  55. data/lib/cool.io/io.rb +194 -0
  56. data/lib/cool.io/iowatcher.rb +17 -0
  57. data/lib/cool.io/listener.rb +99 -0
  58. data/lib/cool.io/loop.rb +122 -0
  59. data/lib/cool.io/meta.rb +49 -0
  60. data/lib/cool.io/server.rb +75 -0
  61. data/lib/cool.io/socket.rb +230 -0
  62. data/lib/cool.io/timer_watcher.rb +17 -0
  63. data/lib/cool.io/version.rb +7 -0
  64. data/lib/coolio.rb +2 -0
  65. data/spec/async_watcher_spec.rb +57 -0
  66. data/spec/dns_spec.rb +43 -0
  67. data/spec/iobuffer_spec.rb +147 -0
  68. data/spec/spec_helper.rb +19 -0
  69. data/spec/stat_watcher_spec.rb +77 -0
  70. data/spec/tcp_server_spec.rb +225 -0
  71. data/spec/tcp_socket_spec.rb +185 -0
  72. data/spec/timer_watcher_spec.rb +59 -0
  73. data/spec/udp_socket_spec.rb +58 -0
  74. data/spec/unix_listener_spec.rb +25 -0
  75. data/spec/unix_server_spec.rb +27 -0
  76. metadata +182 -0
@@ -0,0 +1,148 @@
1
+ /*
2
+ * libev poll fd activity backend
3
+ *
4
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without modifica-
8
+ * tion, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Alternatively, the contents of this file may be used under the terms of
29
+ * the GNU General Public License ("GPL") version 2 or any later version,
30
+ * in which case the provisions of the GPL are applicable instead of
31
+ * the above. If you wish to allow the use of your version of this file
32
+ * only under the terms of the GPL and not to allow others to use your
33
+ * version of this file under the BSD license, indicate your decision
34
+ * by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL. If you do not delete the
36
+ * provisions above, a recipient may use your version of this file under
37
+ * either the BSD or the GPL.
38
+ */
39
+
40
+ #include <poll.h>
41
+
42
+ void inline_size
43
+ pollidx_init (int *base, int count)
44
+ {
45
+ /* consider using memset (.., -1, ...), which is practically guaranteed
46
+ * to work on all systems implementing poll */
47
+ while (count--)
48
+ *base++ = -1;
49
+ }
50
+
51
+ static void
52
+ poll_modify (EV_P_ int fd, int oev, int nev)
53
+ {
54
+ int idx;
55
+
56
+ if (oev == nev)
57
+ return;
58
+
59
+ array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init);
60
+
61
+ idx = pollidxs [fd];
62
+
63
+ if (idx < 0) /* need to allocate a new pollfd */
64
+ {
65
+ pollidxs [fd] = idx = pollcnt++;
66
+ array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2);
67
+ polls [idx].fd = fd;
68
+ }
69
+
70
+ assert (polls [idx].fd == fd);
71
+
72
+ if (nev)
73
+ polls [idx].events =
74
+ (nev & EV_READ ? POLLIN : 0)
75
+ | (nev & EV_WRITE ? POLLOUT : 0);
76
+ else /* remove pollfd */
77
+ {
78
+ pollidxs [fd] = -1;
79
+
80
+ if (expect_true (idx < --pollcnt))
81
+ {
82
+ polls [idx] = polls [pollcnt];
83
+ pollidxs [polls [idx].fd] = idx;
84
+ }
85
+ }
86
+ }
87
+
88
+ static void
89
+ poll_poll (EV_P_ ev_tstamp timeout)
90
+ {
91
+ struct pollfd *p;
92
+ int res;
93
+
94
+ EV_RELEASE_CB;
95
+ res = poll (polls, pollcnt, timeout * 1e3);
96
+ EV_ACQUIRE_CB;
97
+
98
+ if (expect_false (res < 0))
99
+ {
100
+ if (errno == EBADF)
101
+ fd_ebadf (EV_A);
102
+ else if (errno == ENOMEM && !syserr_cb)
103
+ fd_enomem (EV_A);
104
+ else if (errno != EINTR)
105
+ ev_syserr ("(libev) poll");
106
+ }
107
+ else
108
+ for (p = polls; res; ++p)
109
+ {
110
+ assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt));
111
+
112
+ if (expect_false (p->revents)) /* this expect is debatable */
113
+ {
114
+ --res;
115
+
116
+ if (expect_false (p->revents & POLLNVAL))
117
+ fd_kill (EV_A_ p->fd);
118
+ else
119
+ fd_event (
120
+ EV_A_
121
+ p->fd,
122
+ (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
123
+ | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
124
+ );
125
+ }
126
+ }
127
+ }
128
+
129
+ int inline_size
130
+ poll_init (EV_P_ int flags)
131
+ {
132
+ backend_mintime = 1e-3;
133
+ backend_modify = poll_modify;
134
+ backend_poll = poll_poll;
135
+
136
+ pollidxs = 0; pollidxmax = 0;
137
+ polls = 0; pollmax = 0; pollcnt = 0;
138
+
139
+ return EVBACKEND_POLL;
140
+ }
141
+
142
+ void inline_size
143
+ poll_destroy (EV_P)
144
+ {
145
+ ev_free (pollidxs);
146
+ ev_free (polls);
147
+ }
148
+
@@ -0,0 +1,185 @@
1
+ /*
2
+ * libev solaris event port backend
3
+ *
4
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without modifica-
8
+ * tion, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Alternatively, the contents of this file may be used under the terms of
29
+ * the GNU General Public License ("GPL") version 2 or any later version,
30
+ * in which case the provisions of the GPL are applicable instead of
31
+ * the above. If you wish to allow the use of your version of this file
32
+ * only under the terms of the GPL and not to allow others to use your
33
+ * version of this file under the BSD license, indicate your decision
34
+ * by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL. If you do not delete the
36
+ * provisions above, a recipient may use your version of this file under
37
+ * either the BSD or the GPL.
38
+ */
39
+
40
+ /* useful reading:
41
+ *
42
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)
43
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)
44
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)
45
+ * http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)
46
+ * http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget
47
+ * http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)
48
+ * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)
49
+ */
50
+
51
+ #include <sys/types.h>
52
+ #include <sys/time.h>
53
+ #include <poll.h>
54
+ #include <port.h>
55
+ #include <string.h>
56
+ #include <errno.h>
57
+
58
+ void inline_speed
59
+ port_associate_and_check (EV_P_ int fd, int ev)
60
+ {
61
+ if (0 >
62
+ port_associate (
63
+ backend_fd, PORT_SOURCE_FD, fd,
64
+ (ev & EV_READ ? POLLIN : 0)
65
+ | (ev & EV_WRITE ? POLLOUT : 0),
66
+ 0
67
+ )
68
+ )
69
+ {
70
+ if (errno == EBADFD)
71
+ fd_kill (EV_A_ fd);
72
+ else
73
+ ev_syserr ("(libev) port_associate");
74
+ }
75
+ }
76
+
77
+ static void
78
+ port_modify (EV_P_ int fd, int oev, int nev)
79
+ {
80
+ /* we need to reassociate no matter what, as closes are
81
+ * once more silently being discarded.
82
+ */
83
+ if (!nev)
84
+ {
85
+ if (oev)
86
+ port_dissociate (backend_fd, PORT_SOURCE_FD, fd);
87
+ }
88
+ else
89
+ port_associate_and_check (EV_A_ fd, nev);
90
+ }
91
+
92
+ static void
93
+ port_poll (EV_P_ ev_tstamp timeout)
94
+ {
95
+ int res, i;
96
+ struct timespec ts;
97
+ uint_t nget = 1;
98
+
99
+ /* we initialise this to something we will skip in the loop, as */
100
+ /* port_getn can return with nget unchanged, but no indication */
101
+ /* whether it was the original value or has been updated :/ */
102
+ port_events [0].portev_source = 0;
103
+
104
+ EV_RELEASE_CB;
105
+ EV_TS_SET (ts, timeout);
106
+ res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
107
+ EV_ACQUIRE_CB;
108
+
109
+ /* port_getn may or may not set nget on error */
110
+ /* so we rely on port_events [0].portev_source not being updated */
111
+ if (res == -1 && errno != ETIME && errno != EINTR)
112
+ ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
113
+
114
+ for (i = 0; i < nget; ++i)
115
+ {
116
+ if (port_events [i].portev_source == PORT_SOURCE_FD)
117
+ {
118
+ int fd = port_events [i].portev_object;
119
+
120
+ fd_event (
121
+ EV_A_
122
+ fd,
123
+ (port_events [i].portev_events & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
124
+ | (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
125
+ );
126
+
127
+ fd_change (EV_A_ fd, EV__IOFDSET);
128
+ }
129
+ }
130
+
131
+ if (expect_false (nget == port_eventmax))
132
+ {
133
+ ev_free (port_events);
134
+ port_eventmax = array_nextsize (sizeof (port_event_t), port_eventmax, port_eventmax + 1);
135
+ port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
136
+ }
137
+ }
138
+
139
+ int inline_size
140
+ port_init (EV_P_ int flags)
141
+ {
142
+ /* Initialize the kernel queue */
143
+ if ((backend_fd = port_create ()) < 0)
144
+ return 0;
145
+
146
+ assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD));
147
+
148
+ fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
149
+
150
+ /* if my reading of the opensolaris kernel sources are correct, then
151
+ * opensolaris does something very stupid: it checks if the time has already
152
+ * elapsed and doesn't round up if that is the case,m otherwise it DOES round
153
+ * up. Since we can't know what the case is, we need to guess by using a
154
+ * "large enough" timeout. Normally, 1e-9 would be correct.
155
+ */
156
+ backend_mintime = 1e-3; /* needed to compensate for port_getn returning early */
157
+ backend_modify = port_modify;
158
+ backend_poll = port_poll;
159
+
160
+ port_eventmax = 64; /* initial number of events receivable per poll */
161
+ port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax);
162
+
163
+ return EVBACKEND_PORT;
164
+ }
165
+
166
+ void inline_size
167
+ port_destroy (EV_P)
168
+ {
169
+ ev_free (port_events);
170
+ }
171
+
172
+ void inline_size
173
+ port_fork (EV_P)
174
+ {
175
+ close (backend_fd);
176
+
177
+ while ((backend_fd = port_create ()) < 0)
178
+ ev_syserr ("(libev) port");
179
+
180
+ fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
181
+
182
+ /* re-register interest in fds */
183
+ fd_rearm_all (EV_A);
184
+ }
185
+
@@ -0,0 +1,362 @@
1
+ /*
2
+ * libev select fd activity backend
3
+ *
4
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without modifica-
8
+ * tion, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19
+ * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21
+ * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25
+ * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ * Alternatively, the contents of this file may be used under the terms of
29
+ * the GNU General Public License ("GPL") version 2 or any later version,
30
+ * in which case the provisions of the GPL are applicable instead of
31
+ * the above. If you wish to allow the use of your version of this file
32
+ * only under the terms of the GPL and not to allow others to use your
33
+ * version of this file under the BSD license, indicate your decision
34
+ * by deleting the provisions above and replace them with the notice
35
+ * and other provisions required by the GPL. If you do not delete the
36
+ * provisions above, a recipient may use your version of this file under
37
+ * either the BSD or the GPL.
38
+ */
39
+
40
+ #ifndef _WIN32
41
+ /* for unix systems */
42
+ # include <inttypes.h>
43
+ # ifndef __hpux
44
+ /* for REAL unix systems */
45
+ # include <sys/select.h>
46
+ # endif
47
+ #endif
48
+
49
+ #ifndef EV_SELECT_USE_FD_SET
50
+ # ifdef NFDBITS
51
+ # define EV_SELECT_USE_FD_SET 0
52
+ # else
53
+ # define EV_SELECT_USE_FD_SET 1
54
+ # endif
55
+ #endif
56
+
57
+ #if EV_SELECT_IS_WINSOCKET
58
+ # undef EV_SELECT_USE_FD_SET
59
+ # define EV_SELECT_USE_FD_SET 1
60
+ # undef NFDBITS
61
+ # define NFDBITS 0
62
+ #endif
63
+
64
+ #if !EV_SELECT_USE_FD_SET
65
+ # define NFDBYTES (NFDBITS / 8)
66
+ #endif
67
+
68
+ #include <string.h>
69
+
70
+ #ifdef _WIN32
71
+ /*
72
+ ########## COOLIO PATCHERY HO! ##########
73
+
74
+ Ruby undefs FD_* utilities for own implementation.
75
+ It converts fd argument into socket handle internally on Windows,
76
+ so libev should not use Ruby's FD_* utilities.
77
+
78
+ Following FD_* utilities come from MinGW.
79
+ RubyInstaller is built by MinGW so this should work.
80
+ */
81
+ int PASCAL __WSAFDIsSet(SOCKET,fd_set*);
82
+ #define EV_WIN_FD_CLR(fd,set) do { u_int __i;\
83
+ for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\
84
+ if (((fd_set *)(set))->fd_array[__i] == (fd)) {\
85
+ while (__i < ((fd_set *)(set))->fd_count-1) {\
86
+ ((fd_set*)(set))->fd_array[__i] = ((fd_set*)(set))->fd_array[__i+1];\
87
+ __i++;\
88
+ }\
89
+ ((fd_set*)(set))->fd_count--;\
90
+ break;\
91
+ }\
92
+ }\
93
+ } while (0)
94
+ #define EV_WIN_FD_SET(fd, set) do { u_int __i;\
95
+ for (__i = 0; __i < ((fd_set *)(set))->fd_count ; __i++) {\
96
+ if (((fd_set *)(set))->fd_array[__i] == (fd)) {\
97
+ break;\
98
+ }\
99
+ }\
100
+ if (__i == ((fd_set *)(set))->fd_count) {\
101
+ if (((fd_set *)(set))->fd_count < FD_SETSIZE) {\
102
+ ((fd_set *)(set))->fd_array[__i] = (fd);\
103
+ ((fd_set *)(set))->fd_count++;\
104
+ }\
105
+ }\
106
+ } while(0)
107
+ #define EV_WIN_FD_ZERO(set) (((fd_set *)(set))->fd_count=0)
108
+ #define EV_WIN_FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set))
109
+ #define EV_WIN_FD_COUNT(set) (((fd_set *)(set))->fd_count)
110
+ /* ######################################## */
111
+ #else
112
+ #define EV_WIN_FD_CLR FD_CLR
113
+ #define EV_WIN_FD_SET FD_SET
114
+ #define EV_WIN_FD_ZERO FD_ZERO
115
+ #define EV_WIN_FD_ISSET FD_ISSET
116
+ #endif
117
+
118
+ static void
119
+ select_modify (EV_P_ int fd, int oev, int nev)
120
+ {
121
+ if (oev == nev)
122
+ return;
123
+
124
+ {
125
+ #if EV_SELECT_USE_FD_SET
126
+
127
+ #if EV_SELECT_IS_WINSOCKET
128
+ SOCKET handle = anfds [fd].handle;
129
+ #else
130
+ int handle = fd;
131
+ #endif
132
+
133
+ assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE));
134
+
135
+ /* FD_SET is broken on windows (it adds the fd to a set twice or more,
136
+ * which eventually leads to overflows). Need to call it only on changes.
137
+ */
138
+ #if EV_SELECT_IS_WINSOCKET
139
+ if ((oev ^ nev) & EV_READ)
140
+ #endif
141
+ if (nev & EV_READ)
142
+ EV_WIN_FD_SET (handle, (fd_set *)vec_ri);
143
+ else
144
+ EV_WIN_FD_CLR (handle, (fd_set *)vec_ri);
145
+
146
+ #if EV_SELECT_IS_WINSOCKET
147
+ if ((oev ^ nev) & EV_WRITE)
148
+ #endif
149
+ if (nev & EV_WRITE)
150
+ EV_WIN_FD_SET (handle, (fd_set *)vec_wi);
151
+ else
152
+ EV_WIN_FD_CLR (handle, (fd_set *)vec_wi);
153
+
154
+ #else
155
+
156
+ int word = fd / NFDBITS;
157
+ fd_mask mask = 1UL << (fd % NFDBITS);
158
+
159
+ if (expect_false (vec_max <= word))
160
+ {
161
+ int new_max = word + 1;
162
+
163
+ vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES);
164
+ vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */
165
+ vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES);
166
+ vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */
167
+ #ifdef _WIN32
168
+ vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */
169
+ #endif
170
+
171
+ for (; vec_max < new_max; ++vec_max)
172
+ ((fd_mask *)vec_ri) [vec_max] =
173
+ ((fd_mask *)vec_wi) [vec_max] = 0;
174
+ }
175
+
176
+ ((fd_mask *)vec_ri) [word] |= mask;
177
+ if (!(nev & EV_READ))
178
+ ((fd_mask *)vec_ri) [word] &= ~mask;
179
+
180
+ ((fd_mask *)vec_wi) [word] |= mask;
181
+ if (!(nev & EV_WRITE))
182
+ ((fd_mask *)vec_wi) [word] &= ~mask;
183
+ #endif
184
+ }
185
+ }
186
+
187
+ static void
188
+ select_poll (EV_P_ ev_tstamp timeout)
189
+ {
190
+ struct timeval tv;
191
+ int res;
192
+ int fd_setsize;
193
+
194
+ EV_RELEASE_CB;
195
+ EV_TV_SET (tv, timeout);
196
+
197
+ #if EV_SELECT_USE_FD_SET
198
+ fd_setsize = sizeof (fd_set);
199
+ #else
200
+ fd_setsize = vec_max * NFDBYTES;
201
+ #endif
202
+
203
+ memcpy (vec_ro, vec_ri, fd_setsize);
204
+ memcpy (vec_wo, vec_wi, fd_setsize);
205
+
206
+ #ifdef _WIN32
207
+ /* pass in the write set as except set.
208
+ * the idea behind this is to work around a windows bug that causes
209
+ * errors to be reported as an exception and not by setting
210
+ * the writable bit. this is so uncontrollably lame.
211
+ */
212
+ memcpy (vec_eo, vec_wi, fd_setsize);
213
+ res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv);
214
+ #elif EV_SELECT_USE_FD_SET
215
+ fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE;
216
+ res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
217
+ #else
218
+ res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
219
+ #endif
220
+ EV_ACQUIRE_CB;
221
+
222
+ if (expect_false (res < 0))
223
+ {
224
+ #if EV_SELECT_IS_WINSOCKET
225
+ errno = WSAGetLastError ();
226
+ #endif
227
+ #ifdef WSABASEERR
228
+ /* on windows, select returns incompatible error codes, fix this */
229
+ if (errno >= WSABASEERR && errno < WSABASEERR + 1000)
230
+ if (errno == WSAENOTSOCK)
231
+ errno = EBADF;
232
+ else
233
+ errno -= WSABASEERR;
234
+ #endif
235
+
236
+ #ifdef _WIN32
237
+ /* select on windows erroneously returns EINVAL when no fd sets have been
238
+ * provided (this is documented). what microsoft doesn't tell you that this bug
239
+ * exists even when the fd sets _are_ provided, so we have to check for this bug
240
+ * here and emulate by sleeping manually.
241
+ * we also get EINVAL when the timeout is invalid, but we ignore this case here
242
+ * and assume that EINVAL always means: you have to wait manually.
243
+ */
244
+ if (errno == EINVAL)
245
+ {
246
+ if (timeout)
247
+ {
248
+ unsigned long ms = (unsigned long)(timeout * 1e3);
249
+ SleepEx (ms ? ms : 1, TRUE);
250
+ }
251
+
252
+ return;
253
+ }
254
+ #endif
255
+
256
+ if (errno == EBADF)
257
+ fd_ebadf (EV_A);
258
+ else if (errno == ENOMEM && !syserr_cb)
259
+ fd_enomem (EV_A);
260
+ else if (errno != EINTR)
261
+ ev_syserr ("(libev) select");
262
+
263
+ return;
264
+ }
265
+
266
+ #if EV_SELECT_USE_FD_SET
267
+
268
+ {
269
+ int fd;
270
+
271
+ for (fd = 0; fd < anfdmax; ++fd)
272
+ if (anfds [fd].events)
273
+ {
274
+ int events = 0;
275
+ #if EV_SELECT_IS_WINSOCKET
276
+ SOCKET handle = anfds [fd].handle;
277
+ #else
278
+ int handle = fd;
279
+ #endif
280
+
281
+ if (EV_WIN_FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ;
282
+ if (EV_WIN_FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE;
283
+ #ifdef _WIN32
284
+ if (EV_WIN_FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE;
285
+ #endif
286
+
287
+ if (expect_true (events))
288
+ fd_event (EV_A_ fd, events);
289
+ }
290
+ }
291
+
292
+ #else
293
+
294
+ {
295
+ int word, bit;
296
+ for (word = vec_max; word--; )
297
+ {
298
+ fd_mask word_r = ((fd_mask *)vec_ro) [word];
299
+ fd_mask word_w = ((fd_mask *)vec_wo) [word];
300
+ #ifdef _WIN32
301
+ word_w |= ((fd_mask *)vec_eo) [word];
302
+ #endif
303
+
304
+ if (word_r || word_w)
305
+ for (bit = NFDBITS; bit--; )
306
+ {
307
+ fd_mask mask = 1UL << bit;
308
+ int events = 0;
309
+
310
+ events |= word_r & mask ? EV_READ : 0;
311
+ events |= word_w & mask ? EV_WRITE : 0;
312
+
313
+ if (expect_true (events))
314
+ fd_event (EV_A_ word * NFDBITS + bit, events);
315
+ }
316
+ }
317
+ }
318
+
319
+ #endif
320
+ }
321
+
322
+ int inline_size
323
+ select_init (EV_P_ int flags)
324
+ {
325
+ backend_mintime = 1e-6;
326
+ backend_modify = select_modify;
327
+ backend_poll = select_poll;
328
+
329
+ #if EV_SELECT_USE_FD_SET
330
+ vec_ri = ev_malloc (sizeof (fd_set)); EV_WIN_FD_ZERO ((fd_set *)vec_ri);
331
+ vec_ro = ev_malloc (sizeof (fd_set));
332
+ vec_wi = ev_malloc (sizeof (fd_set)); EV_WIN_FD_ZERO ((fd_set *)vec_wi);
333
+ vec_wo = ev_malloc (sizeof (fd_set));
334
+ #ifdef _WIN32
335
+ vec_eo = ev_malloc (sizeof (fd_set));
336
+ #endif
337
+ #else
338
+ vec_max = 0;
339
+ vec_ri = 0;
340
+ vec_ro = 0;
341
+ vec_wi = 0;
342
+ vec_wo = 0;
343
+ #ifdef _WIN32
344
+ vec_eo = 0;
345
+ #endif
346
+ #endif
347
+
348
+ return EVBACKEND_SELECT;
349
+ }
350
+
351
+ void inline_size
352
+ select_destroy (EV_P)
353
+ {
354
+ ev_free (vec_ri);
355
+ ev_free (vec_ro);
356
+ ev_free (vec_wi);
357
+ ev_free (vec_wo);
358
+ #ifdef _WIN32
359
+ ev_free (vec_eo);
360
+ #endif
361
+ }
362
+