nio4r 0.2.0 → 2.7.5

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 (60) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/ext/libev/Changes +232 -3
  4. data/ext/libev/LICENSE +2 -1
  5. data/ext/libev/README +11 -10
  6. data/ext/libev/ev.c +2249 -473
  7. data/ext/libev/ev.h +165 -135
  8. data/ext/libev/ev_epoll.c +68 -36
  9. data/ext/libev/ev_iouring.c +694 -0
  10. data/ext/libev/ev_kqueue.c +44 -18
  11. data/ext/libev/ev_linuxaio.c +620 -0
  12. data/ext/libev/ev_poll.c +28 -20
  13. data/ext/libev/ev_port.c +23 -10
  14. data/ext/libev/ev_select.c +18 -12
  15. data/ext/libev/ev_vars.h +65 -19
  16. data/ext/libev/ev_win32.c +16 -7
  17. data/ext/libev/ev_wrap.h +236 -160
  18. data/ext/nio4r/.clang-format +16 -0
  19. data/ext/nio4r/bytebuffer.c +465 -0
  20. data/ext/nio4r/extconf.rb +44 -35
  21. data/ext/nio4r/libev.h +3 -4
  22. data/ext/nio4r/monitor.c +186 -54
  23. data/ext/nio4r/nio4r.h +17 -23
  24. data/ext/nio4r/nio4r_ext.c +11 -3
  25. data/ext/nio4r/org/nio4r/ByteBuffer.java +295 -0
  26. data/ext/nio4r/org/nio4r/Monitor.java +176 -0
  27. data/ext/nio4r/org/nio4r/Nio4r.java +104 -0
  28. data/ext/nio4r/org/nio4r/Selector.java +297 -0
  29. data/ext/nio4r/selector.c +350 -182
  30. data/lib/nio/bytebuffer.rb +235 -0
  31. data/lib/nio/monitor.rb +100 -8
  32. data/lib/nio/selector.rb +110 -44
  33. data/lib/nio/version.rb +8 -1
  34. data/lib/nio.rb +47 -16
  35. data/lib/nio4r.rb +7 -0
  36. data/license.md +80 -0
  37. data/readme.md +91 -0
  38. data/releases.md +343 -0
  39. data.tar.gz.sig +2 -0
  40. metadata +114 -79
  41. metadata.gz.sig +0 -0
  42. data/.gitignore +0 -20
  43. data/.rspec +0 -4
  44. data/.travis.yml +0 -7
  45. data/CHANGES.md +0 -10
  46. data/Gemfile +0 -4
  47. data/LICENSE.txt +0 -20
  48. data/README.md +0 -171
  49. data/Rakefile +0 -9
  50. data/examples/echo_server.rb +0 -38
  51. data/ext/libev/README.embed +0 -3
  52. data/ext/libev/test_libev_win32.c +0 -123
  53. data/lib/nio/jruby/monitor.rb +0 -42
  54. data/lib/nio/jruby/selector.rb +0 -135
  55. data/nio4r.gemspec +0 -22
  56. data/spec/nio/monitor_spec.rb +0 -46
  57. data/spec/nio/selector_spec.rb +0 -269
  58. data/spec/spec_helper.rb +0 -3
  59. data/tasks/extension.rake +0 -10
  60. data/tasks/rspec.rake +0 -7
data/ext/libev/ev_epoll.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev epoll fd activity backend
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007,2008,2009,2010,2011,2016,2017,2019 Marc Alexander Lehmann <libev@schmorp.de>
5
5
  * All rights reserved.
6
6
  *
7
7
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -93,10 +93,10 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
93
93
  ev.events = (nev & EV_READ ? EPOLLIN : 0)
94
94
  | (nev & EV_WRITE ? EPOLLOUT : 0);
95
95
 
96
- if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev)))
96
+ if (ecb_expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev)))
97
97
  return;
98
98
 
99
- if (expect_true (errno == ENOENT))
99
+ if (ecb_expect_true (errno == ENOENT))
100
100
  {
101
101
  /* if ENOENT then the fd went away, so try to do the right thing */
102
102
  if (!nev)
@@ -105,7 +105,7 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
105
105
  if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev))
106
106
  return;
107
107
  }
108
- else if (expect_true (errno == EEXIST))
108
+ else if (ecb_expect_true (errno == EEXIST))
109
109
  {
110
110
  /* EEXIST means we ignored a previous DEL, but the fd is still active */
111
111
  /* if the kernel mask is the same as the new mask, we assume it hasn't changed */
@@ -115,7 +115,7 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
115
115
  if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))
116
116
  return;
117
117
  }
118
- else if (expect_true (errno == EPERM))
118
+ else if (ecb_expect_true (errno == EPERM))
119
119
  {
120
120
  /* EPERM means the fd is always ready, but epoll is too snobbish */
121
121
  /* to handle it, unlike select or poll. */
@@ -124,12 +124,14 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
124
124
  /* add fd to epoll_eperms, if not already inside */
125
125
  if (!(oldmask & EV_EMASK_EPERM))
126
126
  {
127
- array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2);
127
+ array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, array_needsize_noinit);
128
128
  epoll_eperms [epoll_epermcnt++] = fd;
129
129
  }
130
130
 
131
131
  return;
132
132
  }
133
+ else
134
+ assert (("libev: I/O watcher with invalid fd found in epoll_ctl", errno != EBADF && errno != ELOOP && errno != EINVAL));
133
135
 
134
136
  fd_kill (EV_A_ fd);
135
137
 
@@ -144,14 +146,16 @@ epoll_poll (EV_P_ ev_tstamp timeout)
144
146
  int i;
145
147
  int eventcnt;
146
148
 
149
+ if (ecb_expect_false (epoll_epermcnt))
150
+ timeout = EV_TS_CONST (0.);
151
+
147
152
  /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */
148
153
  /* the default libev max wait time, however. */
149
154
  EV_RELEASE_CB;
150
- eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax,
151
- epoll_epermcnt ? 0 : ev_timeout_to_ms (timeout));
155
+ eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, EV_TS_TO_MSEC (timeout));
152
156
  EV_ACQUIRE_CB;
153
157
 
154
- if (expect_false (eventcnt < 0))
158
+ if (ecb_expect_false (eventcnt < 0))
155
159
  {
156
160
  if (errno != EINTR)
157
161
  ev_syserr ("(libev) epoll_wait");
@@ -168,21 +172,34 @@ epoll_poll (EV_P_ ev_tstamp timeout)
168
172
  int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0)
169
173
  | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0);
170
174
 
171
- /* check for spurious notification */
172
- /* we assume that fd is always in range, as we never shrink the anfds array */
173
- if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
175
+ /*
176
+ * check for spurious notification.
177
+ * this only finds spurious notifications on egen updates
178
+ * other spurious notifications will be found by epoll_ctl, below
179
+ * we assume that fd is always in range, as we never shrink the anfds array
180
+ */
181
+ if (ecb_expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
174
182
  {
175
183
  /* recreate kernel state */
176
- postfork = 1;
184
+ postfork |= 2;
177
185
  continue;
178
186
  }
179
187
 
180
- if (expect_false (got & ~want))
188
+ if (ecb_expect_false (got & ~want))
181
189
  {
182
190
  anfds [fd].emask = want;
183
191
 
184
- /* we received an event but are not interested in it, try mod or del */
185
- /* I don't think we ever need MOD, but let's handle it anyways */
192
+ /*
193
+ * we received an event but are not interested in it, try mod or del
194
+ * this often happens because we optimistically do not unregister fds
195
+ * when we are no longer interested in them, but also when we get spurious
196
+ * notifications for fds from another process. this is partially handled
197
+ * above with the gencounter check (== our fd is not the event fd), and
198
+ * partially here, when epoll_ctl returns an error (== a child has the fd
199
+ * but we closed it).
200
+ * note: for events such as POLLHUP, where we can't know whether it refers
201
+ * to EV_READ or EV_WRITE, we might issue redundant EPOLL_CTL_MOD calls.
202
+ */
186
203
  ev->events = (want & EV_READ ? EPOLLIN : 0)
187
204
  | (want & EV_WRITE ? EPOLLOUT : 0);
188
205
 
@@ -190,7 +207,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
190
207
  /* which is fortunately easy to do for us. */
191
208
  if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev))
192
209
  {
193
- postfork = 1; /* an error occurred, recreate kernel state */
210
+ postfork |= 2; /* an error occurred, recreate kernel state */
194
211
  continue;
195
212
  }
196
213
  }
@@ -199,7 +216,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
199
216
  }
200
217
 
201
218
  /* if the receive array was full, increase its size */
202
- if (expect_false (eventcnt == epoll_eventmax))
219
+ if (ecb_expect_false (eventcnt == epoll_eventmax))
203
220
  {
204
221
  ev_free (epoll_events);
205
222
  epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);
@@ -215,28 +232,43 @@ epoll_poll (EV_P_ ev_tstamp timeout)
215
232
  if (anfds [fd].emask & EV_EMASK_EPERM && events)
216
233
  fd_event (EV_A_ fd, events);
217
234
  else
218
- epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];
235
+ {
236
+ epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];
237
+ anfds [fd].emask = 0;
238
+ }
219
239
  }
220
240
  }
221
241
 
222
- int inline_size
223
- epoll_init (EV_P_ int flags)
242
+ static int
243
+ epoll_epoll_create (void)
224
244
  {
225
- #ifdef EPOLL_CLOEXEC
226
- backend_fd = epoll_create1 (EPOLL_CLOEXEC);
245
+ int fd;
227
246
 
228
- if (backend_fd <= 0)
247
+ #if defined EPOLL_CLOEXEC && !defined __ANDROID__
248
+ fd = epoll_create1 (EPOLL_CLOEXEC);
249
+
250
+ if (fd < 0 && (errno == EINVAL || errno == ENOSYS))
229
251
  #endif
230
- backend_fd = epoll_create (256);
252
+ {
253
+ fd = epoll_create (256);
231
254
 
232
- if (backend_fd < 0)
233
- return 0;
255
+ if (fd >= 0)
256
+ fcntl (fd, F_SETFD, FD_CLOEXEC);
257
+ }
234
258
 
235
- fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
259
+ return fd;
260
+ }
236
261
 
237
- backend_fudge = 0.; /* kernel sources seem to indicate this to be zero */
238
- backend_modify = epoll_modify;
239
- backend_poll = epoll_poll;
262
+ inline_size
263
+ int
264
+ epoll_init (EV_P_ int flags)
265
+ {
266
+ if ((backend_fd = epoll_epoll_create ()) < 0)
267
+ return 0;
268
+
269
+ backend_mintime = EV_TS_CONST (1e-3); /* epoll does sometimes return early, this is just to avoid the worst */
270
+ backend_modify = epoll_modify;
271
+ backend_poll = epoll_poll;
240
272
 
241
273
  epoll_eventmax = 64; /* initial number of events receivable per poll */
242
274
  epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
@@ -244,23 +276,23 @@ epoll_init (EV_P_ int flags)
244
276
  return EVBACKEND_EPOLL;
245
277
  }
246
278
 
247
- void inline_size
279
+ inline_size
280
+ void
248
281
  epoll_destroy (EV_P)
249
282
  {
250
283
  ev_free (epoll_events);
251
284
  array_free (epoll_eperm, EMPTY);
252
285
  }
253
286
 
254
- void inline_size
287
+ ecb_cold
288
+ static void
255
289
  epoll_fork (EV_P)
256
290
  {
257
291
  close (backend_fd);
258
292
 
259
- while ((backend_fd = epoll_create (256)) < 0)
293
+ while ((backend_fd = epoll_epoll_create ()) < 0)
260
294
  ev_syserr ("(libev) epoll_create");
261
295
 
262
- fcntl (backend_fd, F_SETFD, FD_CLOEXEC);
263
-
264
296
  fd_rearm_all (EV_A);
265
297
  }
266
298