polyphony 0.19 → 0.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rubocop.yml +87 -1
  4. data/CHANGELOG.md +35 -0
  5. data/Gemfile.lock +17 -6
  6. data/README.md +200 -139
  7. data/Rakefile +4 -4
  8. data/TODO.md +35 -7
  9. data/bin/poly +11 -0
  10. data/docs/getting-started/getting-started.md +1 -1
  11. data/docs/summary.md +3 -0
  12. data/docs/technical-overview/exception-handling.md +94 -0
  13. data/docs/technical-overview/fiber-scheduling.md +99 -0
  14. data/examples/core/cancel.rb +8 -4
  15. data/examples/core/channel_echo.rb +18 -17
  16. data/examples/core/defer.rb +12 -0
  17. data/examples/core/enumerator.rb +4 -4
  18. data/examples/core/fiber_error.rb +9 -0
  19. data/examples/core/fiber_error_with_backtrace.rb +73 -0
  20. data/examples/core/fork.rb +6 -6
  21. data/examples/core/genserver.rb +16 -8
  22. data/examples/core/lock.rb +3 -3
  23. data/examples/core/move_on.rb +4 -3
  24. data/examples/core/move_on_twice.rb +5 -5
  25. data/examples/core/move_on_with_ensure.rb +8 -11
  26. data/examples/core/move_on_with_value.rb +14 -0
  27. data/examples/core/{multiple_spawn.rb → multiple_spin.rb} +5 -5
  28. data/examples/core/nested_cancel.rb +5 -5
  29. data/examples/core/{nested_multiple_spawn.rb → nested_multiple_spin.rb} +6 -6
  30. data/examples/core/nested_spin.rb +17 -0
  31. data/examples/core/pingpong.rb +21 -0
  32. data/examples/core/pulse.rb +4 -5
  33. data/examples/core/resource.rb +6 -4
  34. data/examples/core/resource_cancel.rb +6 -9
  35. data/examples/core/resource_delegate.rb +3 -3
  36. data/examples/core/sleep.rb +3 -3
  37. data/examples/core/sleep_spin.rb +19 -0
  38. data/examples/core/snooze.rb +32 -0
  39. data/examples/core/spin.rb +14 -0
  40. data/examples/core/{spawn_cancel.rb → spin_cancel.rb} +6 -7
  41. data/examples/core/spin_error.rb +17 -0
  42. data/examples/core/spin_error_backtrace.rb +30 -0
  43. data/examples/core/spin_uncaught_error.rb +15 -0
  44. data/examples/core/supervisor.rb +8 -8
  45. data/examples/core/supervisor_with_cancel_scope.rb +7 -7
  46. data/examples/core/supervisor_with_error.rb +8 -8
  47. data/examples/core/supervisor_with_manual_move_on.rb +6 -7
  48. data/examples/core/suspend.rb +13 -0
  49. data/examples/core/thread.rb +1 -1
  50. data/examples/core/thread_cancel.rb +9 -11
  51. data/examples/core/thread_pool.rb +18 -14
  52. data/examples/core/throttle.rb +7 -7
  53. data/examples/core/timeout.rb +3 -3
  54. data/examples/fs/read.rb +7 -9
  55. data/examples/http/config.ru +7 -3
  56. data/examples/http/cuba.ru +22 -0
  57. data/examples/http/happy_eyeballs.rb +6 -4
  58. data/examples/http/http_client.rb +1 -1
  59. data/examples/http/http_get.rb +1 -1
  60. data/examples/http/http_parse_experiment.rb +21 -16
  61. data/examples/http/http_proxy.rb +28 -26
  62. data/examples/http/http_server.rb +10 -10
  63. data/examples/http/http_server_forked.rb +6 -5
  64. data/examples/http/http_server_throttled.rb +3 -3
  65. data/examples/http/http_ws_server.rb +11 -11
  66. data/examples/http/https_raw_client.rb +1 -1
  67. data/examples/http/https_server.rb +8 -8
  68. data/examples/http/https_wss_server.rb +13 -11
  69. data/examples/http/rack_server.rb +2 -2
  70. data/examples/http/rack_server_https.rb +4 -4
  71. data/examples/http/rack_server_https_forked.rb +5 -5
  72. data/examples/http/websocket_secure_server.rb +6 -6
  73. data/examples/http/websocket_server.rb +5 -5
  74. data/examples/interfaces/pg_client.rb +4 -4
  75. data/examples/interfaces/pg_pool.rb +13 -6
  76. data/examples/interfaces/pg_transaction.rb +5 -4
  77. data/examples/interfaces/redis_channels.rb +15 -11
  78. data/examples/interfaces/redis_client.rb +2 -2
  79. data/examples/interfaces/redis_pubsub.rb +2 -1
  80. data/examples/interfaces/redis_pubsub_perf.rb +13 -9
  81. data/examples/io/backticks.rb +11 -0
  82. data/examples/io/cat.rb +4 -5
  83. data/examples/io/echo_client.rb +9 -4
  84. data/examples/io/echo_client_from_stdin.rb +20 -0
  85. data/examples/io/echo_pipe.rb +7 -8
  86. data/examples/io/echo_server.rb +8 -6
  87. data/examples/io/echo_server_with_timeout.rb +13 -10
  88. data/examples/io/echo_stdin.rb +3 -3
  89. data/examples/io/httparty.rb +2 -2
  90. data/examples/io/httparty_multi.rb +8 -4
  91. data/examples/io/httparty_threaded.rb +6 -2
  92. data/examples/io/io_read.rb +2 -2
  93. data/examples/io/irb.rb +16 -4
  94. data/examples/io/net-http.rb +3 -3
  95. data/examples/io/open.rb +17 -0
  96. data/examples/io/system.rb +3 -3
  97. data/examples/io/tcpserver.rb +15 -0
  98. data/examples/io/tcpsocket.rb +6 -5
  99. data/examples/performance/multi_snooze.rb +29 -0
  100. data/examples/performance/{perf_snooze.rb → snooze.rb} +7 -5
  101. data/examples/performance/snooze_raw.rb +39 -0
  102. data/ext/gyro/async.c +165 -0
  103. data/ext/gyro/child.c +167 -0
  104. data/ext/{ev → gyro}/extconf.rb +4 -3
  105. data/ext/gyro/gyro.c +316 -0
  106. data/ext/{ev/ev.h → gyro/gyro.h} +12 -7
  107. data/ext/gyro/gyro_ext.c +23 -0
  108. data/ext/{ev → gyro}/io.c +65 -57
  109. data/ext/{ev → gyro}/libev.h +0 -0
  110. data/ext/gyro/signal.c +117 -0
  111. data/ext/{ev → gyro}/socket.c +61 -6
  112. data/ext/gyro/timer.c +199 -0
  113. data/ext/libev/Changes +35 -0
  114. data/ext/libev/README +2 -1
  115. data/ext/libev/ev.c +213 -151
  116. data/ext/libev/ev.h +95 -88
  117. data/ext/libev/ev_epoll.c +26 -15
  118. data/ext/libev/ev_kqueue.c +11 -5
  119. data/ext/libev/ev_linuxaio.c +642 -0
  120. data/ext/libev/ev_poll.c +13 -8
  121. data/ext/libev/ev_port.c +5 -2
  122. data/ext/libev/ev_vars.h +14 -3
  123. data/ext/libev/ev_wrap.h +16 -0
  124. data/lib/ev_ext.bundle +0 -0
  125. data/lib/polyphony.rb +46 -50
  126. data/lib/polyphony/auto_run.rb +12 -0
  127. data/lib/polyphony/core/cancel_scope.rb +11 -7
  128. data/lib/polyphony/core/channel.rb +16 -9
  129. data/lib/polyphony/core/coprocess.rb +101 -51
  130. data/lib/polyphony/core/exceptions.rb +14 -12
  131. data/lib/polyphony/core/resource_pool.rb +21 -8
  132. data/lib/polyphony/core/supervisor.rb +10 -5
  133. data/lib/polyphony/core/sync.rb +7 -6
  134. data/lib/polyphony/core/thread.rb +4 -4
  135. data/lib/polyphony/core/thread_pool.rb +4 -4
  136. data/lib/polyphony/core/throttler.rb +6 -4
  137. data/lib/polyphony/extensions/core.rb +253 -0
  138. data/lib/polyphony/extensions/io.rb +28 -16
  139. data/lib/polyphony/extensions/openssl.rb +2 -1
  140. data/lib/polyphony/extensions/socket.rb +47 -52
  141. data/lib/polyphony/http.rb +4 -3
  142. data/lib/polyphony/http/agent.rb +68 -57
  143. data/lib/polyphony/http/server.rb +5 -5
  144. data/lib/polyphony/http/server/http1.rb +268 -0
  145. data/lib/polyphony/http/server/http2.rb +62 -0
  146. data/lib/polyphony/http/server/http2_stream.rb +104 -0
  147. data/lib/polyphony/http/server/rack.rb +64 -0
  148. data/lib/polyphony/http/server/request.rb +119 -0
  149. data/lib/polyphony/net.rb +26 -15
  150. data/lib/polyphony/postgres.rb +17 -13
  151. data/lib/polyphony/redis.rb +16 -15
  152. data/lib/polyphony/version.rb +1 -1
  153. data/lib/polyphony/websocket.rb +11 -4
  154. data/polyphony.gemspec +13 -9
  155. data/test/eg.rb +27 -0
  156. data/test/helper.rb +25 -0
  157. data/test/run.rb +5 -0
  158. data/test/test_async.rb +33 -0
  159. data/test/test_coprocess.rb +239 -77
  160. data/test/test_core.rb +95 -61
  161. data/test/test_gyro.rb +148 -0
  162. data/test/test_http_server.rb +313 -0
  163. data/test/test_io.rb +79 -27
  164. data/test/test_kernel.rb +22 -12
  165. data/test/test_signal.rb +36 -0
  166. data/test/test_timer.rb +24 -0
  167. metadata +89 -33
  168. data/examples/core/nested_async.rb +0 -17
  169. data/examples/core/next_tick.rb +0 -12
  170. data/examples/core/sleep_spawn.rb +0 -19
  171. data/examples/core/spawn.rb +0 -14
  172. data/examples/core/spawn_error.rb +0 -28
  173. data/examples/performance/perf_multi_snooze.rb +0 -21
  174. data/ext/ev/async.c +0 -168
  175. data/ext/ev/child.c +0 -169
  176. data/ext/ev/ev_ext.c +0 -23
  177. data/ext/ev/ev_module.c +0 -242
  178. data/ext/ev/signal.c +0 -119
  179. data/ext/ev/timer.c +0 -197
  180. data/lib/polyphony/core/fiber_pool.rb +0 -98
  181. data/lib/polyphony/extensions/kernel.rb +0 -169
  182. data/lib/polyphony/http/http1_adapter.rb +0 -254
  183. data/lib/polyphony/http/http2_adapter.rb +0 -157
  184. data/lib/polyphony/http/rack.rb +0 -25
  185. data/lib/polyphony/http/request.rb +0 -66
  186. data/test/test_ev.rb +0 -110
@@ -1,15 +1,25 @@
1
- #include "ev.h"
1
+ #include "gyro.h"
2
2
  #include <sys/socket.h>
3
3
 
4
4
  static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE io);
5
5
  static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE io);
6
6
 
7
+ static VALUE Socket_accept(VALUE sock);
8
+
9
+ static VALUE cTCPSocket;
10
+
7
11
  void Init_Socket() {
8
12
  rb_require("socket");
9
13
  VALUE cBasicSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
10
14
 
11
15
  rb_define_method(cBasicSocket, "send", BasicSocket_send, -1);
12
16
  rb_define_method(cBasicSocket, "recv", BasicSocket_recv, -1);
17
+
18
+ VALUE cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
19
+
20
+ rb_define_method(cSocket, "accept", Socket_accept, 0);
21
+
22
+ cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
13
23
  }
14
24
 
15
25
  ///////////////////////////////////////////////////////////////////////////
@@ -72,7 +82,7 @@ rsock_send_blocking(void *data)
72
82
  ///////////////////////////////////////////////////////////////////////////
73
83
 
74
84
  static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
75
- VALUE underlying_socket = rb_iv_get(sock, "@socket");
85
+ VALUE underlying_socket = rb_iv_get(sock, "@io");
76
86
  if (!NIL_P(underlying_socket)) sock = underlying_socket;
77
87
  struct rsock_send_arg arg;
78
88
  VALUE flags, to;
@@ -85,6 +95,7 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
85
95
  rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
86
96
 
87
97
  StringValue(arg.mesg);
98
+
88
99
  if (!NIL_P(to)) {
89
100
  SockAddrStringValue(to);
90
101
  to = rb_str_new4(to);
@@ -102,15 +113,16 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
102
113
  arg.fd = fptr->fd;
103
114
  arg.flags = NUM2INT(flags);
104
115
  while ((n = (ssize_t)func(&arg)) < 0) {
105
- if (write_watcher == Qnil)
116
+ if (write_watcher == Qnil) {
106
117
  write_watcher = IO_write_watcher(sock);
107
- EV_IO_await(write_watcher);
118
+ }
119
+ Gyro_IO_await(write_watcher);
108
120
  }
109
121
  return SSIZET2NUM(n);
110
122
  }
111
123
 
112
124
  static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
113
- VALUE underlying_socket = rb_iv_get(sock, "@socket");
125
+ VALUE underlying_socket = rb_iv_get(sock, "@io");
114
126
  if (!NIL_P(underlying_socket)) sock = underlying_socket;
115
127
  long len = argc >= 1 ? NUM2LONG(argv[0]) : 8192;
116
128
  if (len < 0) {
@@ -141,7 +153,7 @@ static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
141
153
  if (e == EWOULDBLOCK || e == EAGAIN) {
142
154
  if (read_watcher == Qnil)
143
155
  read_watcher = IO_read_watcher(sock);
144
- EV_IO_await(read_watcher);
156
+ Gyro_IO_await(read_watcher);
145
157
  }
146
158
  else
147
159
  rb_syserr_fail(e, strerror(e));
@@ -158,4 +170,47 @@ static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
158
170
  return Qnil;
159
171
 
160
172
  return str;
173
+ }
174
+
175
+ static VALUE Socket_accept(VALUE sock) {
176
+ rb_io_t *fptr;
177
+ int fd;
178
+ struct sockaddr addr;
179
+ socklen_t len = (socklen_t)sizeof addr;
180
+ VALUE read_watcher = Qnil;
181
+
182
+ GetOpenFile(sock, fptr);
183
+ rb_io_set_nonblock(fptr);
184
+
185
+ while (1) {
186
+ fd = accept(fptr->fd, &addr, &len);
187
+
188
+ if (fd < 0) {
189
+ int e = errno;
190
+ if (e == EWOULDBLOCK || e == EAGAIN) {
191
+ if (read_watcher == Qnil)
192
+ read_watcher = IO_read_watcher(sock);
193
+ Gyro_IO_await(read_watcher);
194
+ }
195
+ else
196
+ rb_syserr_fail(e, strerror(e));
197
+ // rb_syserr_fail_path(e, fptr->pathv);
198
+ }
199
+ else {
200
+ VALUE connection = rb_obj_alloc(cTCPSocket);
201
+ rb_io_t *fp;
202
+ MakeOpenFile(connection, fp);
203
+ rb_update_max_fd(fd);
204
+ fp->fd = fd;
205
+ fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
206
+ rb_io_ascii8bit_binmode(connection);
207
+ rb_io_set_nonblock(fp);
208
+ rb_io_synchronized(fp);
209
+ // if (rsock_do_not_reverse_lookup) {
210
+ // fp->mode |= FMODE_NOREVLOOKUP;
211
+ // }
212
+
213
+ return connection;
214
+ }
215
+ }
161
216
  }
data/ext/gyro/timer.c ADDED
@@ -0,0 +1,199 @@
1
+ #include "gyro.h"
2
+
3
+ struct Gyro_Timer {
4
+ struct ev_timer ev_timer;
5
+ int active;
6
+ double after;
7
+ double repeat;
8
+ VALUE self;
9
+ VALUE callback;
10
+ VALUE fiber;
11
+ };
12
+
13
+ static VALUE cGyro_Timer = Qnil;
14
+
15
+ /* Allocator/deallocator */
16
+ static VALUE Gyro_Timer_allocate(VALUE klass);
17
+ static void Gyro_Timer_mark(void *ptr);
18
+ static void Gyro_Timer_free(void *ptr);
19
+ static size_t Gyro_Timer_size(const void *ptr);
20
+
21
+ /* Methods */
22
+ static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat);
23
+
24
+ static VALUE Gyro_Timer_start(VALUE self);
25
+ static VALUE Gyro_Timer_stop(VALUE self);
26
+ static VALUE Gyro_Timer_reset(VALUE self);
27
+ static VALUE Gyro_Timer_await(VALUE self);
28
+
29
+ void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
30
+
31
+ /* Timer encapsulates an timer watcher */
32
+ void Init_Gyro_Timer() {
33
+ cGyro_Timer = rb_define_class_under(mGyro, "Timer", rb_cData);
34
+ rb_define_alloc_func(cGyro_Timer, Gyro_Timer_allocate);
35
+
36
+ rb_define_method(cGyro_Timer, "initialize", Gyro_Timer_initialize, 2);
37
+ rb_define_method(cGyro_Timer, "start", Gyro_Timer_start, 0);
38
+ rb_define_method(cGyro_Timer, "stop", Gyro_Timer_stop, 0);
39
+ rb_define_method(cGyro_Timer, "reset", Gyro_Timer_reset, 0);
40
+ rb_define_method(cGyro_Timer, "await", Gyro_Timer_await, 0);
41
+ }
42
+
43
+ static const rb_data_type_t Gyro_Timer_type = {
44
+ "Gyro_Timer",
45
+ {Gyro_Timer_mark, Gyro_Timer_free, Gyro_Timer_size,},
46
+ 0, 0,
47
+ RUBY_TYPED_FREE_IMMEDIATELY,
48
+ };
49
+
50
+ static VALUE Gyro_Timer_allocate(VALUE klass) {
51
+ struct Gyro_Timer *timer = (struct Gyro_Timer *)xmalloc(sizeof(struct Gyro_Timer));
52
+ return TypedData_Wrap_Struct(klass, &Gyro_Timer_type, timer);
53
+ }
54
+
55
+ static void Gyro_Timer_mark(void *ptr) {
56
+ struct Gyro_Timer *timer = ptr;
57
+ if (timer->callback != Qnil) {
58
+ rb_gc_mark(timer->callback);
59
+ }
60
+ if (timer->fiber != Qnil) {
61
+ rb_gc_mark(timer->fiber);
62
+ }
63
+ }
64
+
65
+ static void Gyro_Timer_free(void *ptr) {
66
+ struct Gyro_Timer *timer = ptr;
67
+ if (timer->active) {
68
+ ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
69
+ }
70
+ xfree(timer);
71
+ }
72
+
73
+ static size_t Gyro_Timer_size(const void *ptr) {
74
+ return sizeof(struct Gyro_Timer);
75
+ }
76
+
77
+ #define GetGyro_Timer(obj, timer) \
78
+ TypedData_Get_Struct((obj), struct Gyro_Timer, &Gyro_Timer_type, (timer))
79
+
80
+ static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
81
+ struct Gyro_Timer *timer;
82
+
83
+ GetGyro_Timer(self, timer);
84
+
85
+ timer->self = self;
86
+ timer->callback = Qnil;
87
+ timer->fiber = Qnil;
88
+ timer->after = NUM2DBL(after);
89
+ timer->repeat = NUM2DBL(repeat);
90
+ timer->active = 0;
91
+
92
+ ev_timer_init(&timer->ev_timer, Gyro_Timer_callback, timer->after, timer->repeat);
93
+
94
+ return Qnil;
95
+ }
96
+
97
+ void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
98
+ VALUE fiber;
99
+ VALUE resume_value;
100
+ struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
101
+
102
+ // if (!timer->active) {
103
+ // return;
104
+ // }
105
+
106
+ if (!timer->repeat) {
107
+ timer->active = 0;
108
+ Gyro_del_watcher_ref(timer->self);
109
+ }
110
+
111
+ if (timer->fiber != Qnil) {
112
+ ev_timer_stop(EV_DEFAULT, ev_timer);
113
+ Gyro_del_watcher_ref(timer->self);
114
+ timer->active = 0;
115
+ fiber = timer->fiber;
116
+ timer->fiber = Qnil;
117
+ resume_value = DBL2NUM(timer->after);
118
+ SCHEDULE_FIBER(fiber, 1, resume_value);
119
+ }
120
+ else if (timer->callback != Qnil) {
121
+ rb_funcall(timer->callback, ID_call, 1, Qtrue);
122
+ }
123
+ }
124
+
125
+ static VALUE Gyro_Timer_start(VALUE self) {
126
+ struct Gyro_Timer *timer;
127
+ GetGyro_Timer(self, timer);
128
+
129
+ if (rb_block_given_p()) {
130
+ timer->callback = rb_block_proc();
131
+ }
132
+
133
+ if (!timer->active) {
134
+ ev_timer_start(EV_DEFAULT, &timer->ev_timer);
135
+ timer->active = 1;
136
+ Gyro_add_watcher_ref(self);
137
+ }
138
+
139
+ return self;
140
+ }
141
+
142
+ static VALUE Gyro_Timer_stop(VALUE self) {
143
+ struct Gyro_Timer *timer;
144
+ GetGyro_Timer(self, timer);
145
+
146
+ if (timer->active) {
147
+ ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
148
+ timer->active = 0;
149
+ Gyro_del_watcher_ref(self);
150
+ }
151
+
152
+ return self;
153
+ }
154
+
155
+ static VALUE Gyro_Timer_reset(VALUE self) {
156
+ struct Gyro_Timer *timer;
157
+ int prev_active;
158
+ GetGyro_Timer(self, timer);
159
+
160
+ prev_active = timer->active;
161
+
162
+ if (prev_active) {
163
+ ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
164
+ }
165
+ ev_timer_set(&timer->ev_timer, timer->after, timer->repeat);
166
+ ev_timer_start(EV_DEFAULT, &timer->ev_timer);
167
+ if (!prev_active) {
168
+ timer->active = 1;
169
+ Gyro_add_watcher_ref(self);
170
+ }
171
+
172
+ return self;
173
+ }
174
+
175
+ static VALUE Gyro_Timer_await(VALUE self) {
176
+ struct Gyro_Timer *timer;
177
+ VALUE ret;
178
+
179
+ GetGyro_Timer(self, timer);
180
+
181
+ timer->fiber = rb_fiber_current();
182
+ timer->active = 1;
183
+ ev_timer_start(EV_DEFAULT, &timer->ev_timer);
184
+ Gyro_add_watcher_ref(self);
185
+
186
+ ret = YIELD_TO_REACTOR();
187
+
188
+ // fiber is resumed, check if resumed value is an exception
189
+ if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
190
+ if (timer->active) {
191
+ timer->active = 0;
192
+ ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
193
+ }
194
+ return rb_funcall(ret, ID_raise, 1, ret);
195
+ }
196
+ else {
197
+ return ret;
198
+ }
199
+ }
data/ext/libev/Changes CHANGED
@@ -1,5 +1,40 @@
1
1
  Revision history for libev, a high-performance and full-featured event loop.
2
2
 
3
+ 4.27 Thu Jun 27 22:43:44 CEST 2019
4
+ - linux aio backend almost complete rewritten to work around its
5
+ limitations.
6
+ - epoll backend now mandatory for linux aio backend.
7
+ - fail assertions more aggressively on invalid fd's detected
8
+ in the event loop, do not just silently fd_kill in case of
9
+ user error.
10
+ - ev_io_start/ev_io_stop now verify the watcher fd using
11
+ a syscall when EV_VERIFY is 2 or higher.
12
+
13
+ 4.26 (EV only)
14
+ - update to libecb 0x00010006.
15
+ - new experimental linux aio backend (linux 4.18+).
16
+ - removed redundant 0-ptr check in ev_once.
17
+ - updated/extended ev_set_allocator documentation.
18
+ - replaced EMPTY2 macro by array_needsize_noinit.
19
+ - minor code cleanups.
20
+ - epoll backend now uses epoll_create1 also after fork.
21
+
22
+ 4.25 Fri Dec 21 07:49:20 CET 2018
23
+ - INCOMPATIBLE CHANGE: EV_THROW was renamed to EV_NOEXCEPT
24
+ (EV_THROW still provided) and now uses noexcept on C++11 or newer.
25
+ - move the darwin select workaround highe rin ev.c, as newer versions of
26
+ darwin managed to break their broken select even more.
27
+ - ANDROID => __ANDROID__ (reported by enh@google.com).
28
+ - disable epoll_create1 on android because it has broken header files
29
+ and google is unwilling to fix them (reported by enh@google.com).
30
+ - avoid a minor compilation warning on win32.
31
+ - c++: remove deprecated dynamic throw() specifications.
32
+ - c++: improve the (unsupported) bad_loop exception class.
33
+ - backport perl ev_periodic example to C, untested.
34
+ - update libecb, biggets change is to include a memory fence
35
+ in ECB_MEMORY_FENCE_RELEASE on x86/amd64.
36
+ - minor autoconf/automake modernisation.
37
+
3
38
  4.24 Wed Dec 28 05:19:55 CET 2016
4
39
  - bump version to 4.24, as the release tarball inexplicably
5
40
  didn't have the right version in ev.h, even though the cvs-tagged
data/ext/libev/README CHANGED
@@ -18,7 +18,8 @@ ABOUT
18
18
  - extensive and detailed, readable documentation (not doxygen garbage).
19
19
  - fully supports fork, can detect fork in various ways and automatically
20
20
  re-arms kernel mechanisms that do not support fork.
21
- - highly optimised select, poll, epoll, kqueue and event ports backends.
21
+ - highly optimised select, poll, linux epoll, linux aio, bsd kqueue
22
+ and solaris event ports backends.
22
23
  - filesystem object (path) watching (with optional linux inotify support).
23
24
  - wallclock-based times (using absolute time, cron-like).
24
25
  - relative timers/timeouts (handle time jumps).
data/ext/libev/ev.c CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * libev event processing core, watcher management
3
3
  *
4
- * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev@schmorp.de>
4
+ * Copyright (c) 2007-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-
@@ -40,6 +40,10 @@
40
40
  /* ########## NIO4R PATCHERY HO! ########## */
41
41
  #include "ruby.h"
42
42
  #include "ruby/thread.h"
43
+
44
+ #ifdef __APPLE__
45
+ #include <AvailabilityMacros.h>
46
+ #endif
43
47
  /* ######################################## */
44
48
 
45
49
  /* this big block deduces configuration from config.h */
@@ -122,6 +126,15 @@
122
126
  # define EV_USE_EPOLL 0
123
127
  # endif
124
128
 
129
+ # if HAVE_LINUX_AIO_ABI_H
130
+ # ifndef EV_USE_LINUXAIO
131
+ # define EV_USE_LINUXAIO EV_FEATURE_BACKENDS
132
+ # endif
133
+ # else
134
+ # undef EV_USE_LINUXAIO
135
+ # define EV_USE_LINUXAIO 0
136
+ # endif
137
+
125
138
  # if HAVE_KQUEUE && HAVE_SYS_EVENT_H
126
139
  # ifndef EV_USE_KQUEUE
127
140
  # define EV_USE_KQUEUE EV_FEATURE_BACKENDS
@@ -169,6 +182,16 @@
169
182
 
170
183
  #endif
171
184
 
185
+ /* OS X, in its infinite idiocy, actually HARDCODES
186
+ * a limit of 1024 into their select. Where people have brains,
187
+ * OS X engineers apparently have a vacuum. Or maybe they were
188
+ * ordered to have a vacuum, or they do anything for money.
189
+ * This might help. Or not.
190
+ * Note that this must be defined early, as other include files
191
+ * will rely on this define as well.
192
+ */
193
+ #define _DARWIN_UNLIMITED_SELECT 1
194
+
172
195
  #include <stdlib.h>
173
196
  #include <string.h>
174
197
  #include <fcntl.h>
@@ -216,14 +239,6 @@
216
239
  # undef EV_AVOID_STDIO
217
240
  #endif
218
241
 
219
- /* OS X, in its infinite idiocy, actually HARDCODES
220
- * a limit of 1024 into their select. Where people have brains,
221
- * OS X engineers apparently have a vacuum. Or maybe they were
222
- * ordered to have a vacuum, or they do anything for money.
223
- * This might help. Or not.
224
- */
225
- #define _DARWIN_UNLIMITED_SELECT 1
226
-
227
242
  /* this block tries to deduce configuration from header-defined symbols and defaults */
228
243
 
229
244
  /* try to deduce the maximum number of signals on this platform */
@@ -370,7 +385,7 @@
370
385
  # define EV_HEAP_CACHE_AT EV_FEATURE_DATA
371
386
  #endif
372
387
 
373
- #ifdef ANDROID
388
+ #ifdef __ANDROID__
374
389
  /* supposedly, android doesn't typedef fd_mask */
375
390
  # undef EV_USE_SELECT
376
391
  # define EV_USE_SELECT 0
@@ -424,6 +439,14 @@
424
439
  # endif
425
440
  #endif
426
441
 
442
+ #if EV_USE_LINUXAIO
443
+ # include <sys/syscall.h>
444
+ # if !SYS_io_getevents || !EV_USE_EPOLL /* ev_linxaio uses ev_poll.c:ev_epoll_create */
445
+ # undef EV_USE_LINUXAIO
446
+ # define EV_USE_LINUXAIO 0
447
+ # endif
448
+ #endif
449
+
427
450
  #if EV_USE_INOTIFY
428
451
  # include <sys/statfs.h>
429
452
  # include <sys/inotify.h>
@@ -539,7 +562,7 @@ struct signalfd_siginfo
539
562
  #define ECB_H
540
563
 
541
564
  /* 16 bits major, 16 bits minor */
542
- #define ECB_VERSION 0x00010005
565
+ #define ECB_VERSION 0x00010006
543
566
 
544
567
  #ifdef _WIN32
545
568
  typedef signed char int8_t;
@@ -614,6 +637,8 @@ struct signalfd_siginfo
614
637
 
615
638
  #define ECB_CPP (__cplusplus+0)
616
639
  #define ECB_CPP11 (__cplusplus >= 201103L)
640
+ #define ECB_CPP14 (__cplusplus >= 201402L)
641
+ #define ECB_CPP17 (__cplusplus >= 201703L)
617
642
 
618
643
  #if ECB_CPP
619
644
  #define ECB_C 0
@@ -625,6 +650,7 @@ struct signalfd_siginfo
625
650
 
626
651
  #define ECB_C99 (ECB_STDC_VERSION >= 199901L)
627
652
  #define ECB_C11 (ECB_STDC_VERSION >= 201112L)
653
+ #define ECB_C17 (ECB_STDC_VERSION >= 201710L)
628
654
 
629
655
  #if ECB_CPP
630
656
  #define ECB_EXTERN_C extern "C"
@@ -660,14 +686,15 @@ struct signalfd_siginfo
660
686
 
661
687
  #ifndef ECB_MEMORY_FENCE
662
688
  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
689
+ #define ECB_MEMORY_FENCE_RELAXED __asm__ __volatile__ ("" : : : "memory")
663
690
  #if __i386 || __i386__
664
691
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
665
692
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
666
- #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
693
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory")
667
694
  #elif ECB_GCC_AMD64
668
695
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
669
696
  #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory")
670
- #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
697
+ #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory")
671
698
  #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
672
699
  #define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
673
700
  #elif defined __ARM_ARCH_2__ \
@@ -719,12 +746,14 @@ struct signalfd_siginfo
719
746
  #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST)
720
747
  #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
721
748
  #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
749
+ #define ECB_MEMORY_FENCE_RELAXED __atomic_thread_fence (__ATOMIC_RELAXED)
722
750
 
723
751
  #elif ECB_CLANG_EXTENSION(c_atomic)
724
752
  /* see comment below (stdatomic.h) about the C11 memory model. */
725
753
  #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
726
754
  #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
727
755
  #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
756
+ #define ECB_MEMORY_FENCE_RELAXED __c11_atomic_thread_fence (__ATOMIC_RELAXED)
728
757
 
729
758
  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
730
759
  #define ECB_MEMORY_FENCE __sync_synchronize ()
@@ -744,9 +773,10 @@ struct signalfd_siginfo
744
773
  #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
745
774
  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
746
775
  #include <mbarrier.h>
747
- #define ECB_MEMORY_FENCE __machine_rw_barrier ()
748
- #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier ()
749
- #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier ()
776
+ #define ECB_MEMORY_FENCE __machine_rw_barrier ()
777
+ #define ECB_MEMORY_FENCE_ACQUIRE __machine_acq_barrier ()
778
+ #define ECB_MEMORY_FENCE_RELEASE __machine_rel_barrier ()
779
+ #define ECB_MEMORY_FENCE_RELAXED __compiler_barrier ()
750
780
  #elif __xlC__
751
781
  #define ECB_MEMORY_FENCE __sync ()
752
782
  #endif
@@ -757,15 +787,9 @@ struct signalfd_siginfo
757
787
  /* we assume that these memory fences work on all variables/all memory accesses, */
758
788
  /* not just C11 atomics and atomic accesses */
759
789
  #include <stdatomic.h>
760
- /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
761
- /* any fence other than seq_cst, which isn't very efficient for us. */
762
- /* Why that is, we don't know - either the C11 memory model is quite useless */
763
- /* for most usages, or gcc and clang have a bug */
764
- /* I *currently* lean towards the latter, and inefficiently implement */
765
- /* all three of ecb's fences as a seq_cst fence */
766
- /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
767
- /* for all __atomic_thread_fence's except seq_cst */
768
790
  #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst)
791
+ #define ECB_MEMORY_FENCE_ACQUIRE atomic_thread_fence (memory_order_acquire)
792
+ #define ECB_MEMORY_FENCE_RELEASE atomic_thread_fence (memory_order_release)
769
793
  #endif
770
794
  #endif
771
795
 
@@ -795,6 +819,10 @@ struct signalfd_siginfo
795
819
  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
796
820
  #endif
797
821
 
822
+ #if !defined ECB_MEMORY_FENCE_RELAXED && defined ECB_MEMORY_FENCE
823
+ #define ECB_MEMORY_FENCE_RELAXED ECB_MEMORY_FENCE /* very heavy-handed */
824
+ #endif
825
+
798
826
  /*****************************************************************************/
799
827
 
800
828
  #if ECB_CPP
@@ -1545,8 +1573,7 @@ ecb_binary32_to_binary16 (uint32_t x)
1545
1573
  # define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
1546
1574
  #endif
1547
1575
 
1548
- #define EMPTY /* required for microsofts broken pseudo-c compiler */
1549
- #define EMPTY2(a,b) /* used to suppress some warnings */
1576
+ #define EMPTY /* required for microsofts broken pseudo-c compiler */
1550
1577
 
1551
1578
  typedef ev_watcher *W;
1552
1579
  typedef ev_watcher_list *WL;
@@ -1581,6 +1608,10 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
1581
1608
 
1582
1609
  /*****************************************************************************/
1583
1610
 
1611
+ #if EV_USE_LINUXAIO
1612
+ # include <linux/aio_abi.h> /* probably only needed for aio_context_t */
1613
+ #endif
1614
+
1584
1615
  /* define a suitable floor function (only used by periodics atm) */
1585
1616
 
1586
1617
  #if EV_USE_FLOOR
@@ -1682,11 +1713,11 @@ ev_printerr (const char *msg)
1682
1713
  }
1683
1714
  #endif
1684
1715
 
1685
- static void (*syserr_cb)(const char *msg) EV_THROW;
1716
+ static void (*syserr_cb)(const char *msg) EV_NOEXCEPT;
1686
1717
 
1687
1718
  ecb_cold
1688
1719
  void
1689
- ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW
1720
+ ev_set_syserr_cb (void (*cb)(const char *msg) EV_NOEXCEPT) EV_NOEXCEPT
1690
1721
  {
1691
1722
  syserr_cb = cb;
1692
1723
  }
@@ -1715,7 +1746,7 @@ ev_syserr (const char *msg)
1715
1746
  }
1716
1747
 
1717
1748
  static void *
1718
- ev_realloc_emul (void *ptr, long size) EV_THROW
1749
+ ev_realloc_emul (void *ptr, size_t size) EV_NOEXCEPT
1719
1750
  {
1720
1751
  /* some systems, notably openbsd and darwin, fail to properly
1721
1752
  * implement realloc (x, 0) (as required by both ansi c-89 and
@@ -1731,17 +1762,17 @@ ev_realloc_emul (void *ptr, long size) EV_THROW
1731
1762
  return 0;
1732
1763
  }
1733
1764
 
1734
- static void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul;
1765
+ static void *(*alloc)(void *ptr, size_t size) EV_NOEXCEPT = ev_realloc_emul;
1735
1766
 
1736
1767
  ecb_cold
1737
1768
  void
1738
- ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW
1769
+ ev_set_allocator (void *(*cb)(void *ptr, size_t size) EV_NOEXCEPT) EV_NOEXCEPT
1739
1770
  {
1740
1771
  alloc = cb;
1741
1772
  }
1742
1773
 
1743
1774
  inline_speed void *
1744
- ev_realloc (void *ptr, long size)
1775
+ ev_realloc (void *ptr, size_t size)
1745
1776
  {
1746
1777
  ptr = alloc (ptr, size);
1747
1778
 
@@ -1772,7 +1803,7 @@ typedef struct
1772
1803
  WL head;
1773
1804
  unsigned char events; /* the events watched for */
1774
1805
  unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
1775
- unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
1806
+ unsigned char emask; /* some backends store the actual kernel mask in here */
1776
1807
  unsigned char unused;
1777
1808
  #if EV_USE_EPOLL
1778
1809
  unsigned int egen; /* generation counter to counter epoll bugs */
@@ -1862,7 +1893,7 @@ typedef struct
1862
1893
 
1863
1894
  #ifndef EV_HAVE_EV_TIME
1864
1895
  ev_tstamp
1865
- ev_time (void) EV_THROW
1896
+ ev_time (void) EV_NOEXCEPT
1866
1897
  {
1867
1898
  #if EV_USE_REALTIME
1868
1899
  if (expect_true (have_realtime))
@@ -1896,14 +1927,14 @@ get_clock (void)
1896
1927
 
1897
1928
  #if EV_MULTIPLICITY
1898
1929
  ev_tstamp
1899
- ev_now (EV_P) EV_THROW
1930
+ ev_now (EV_P) EV_NOEXCEPT
1900
1931
  {
1901
1932
  return ev_rt_now;
1902
1933
  }
1903
1934
  #endif
1904
1935
 
1905
1936
  void
1906
- ev_sleep (ev_tstamp delay) EV_THROW
1937
+ ev_sleep (ev_tstamp delay) EV_NOEXCEPT
1907
1938
  {
1908
1939
  if (delay > 0.)
1909
1940
  {
@@ -1913,6 +1944,8 @@ ev_sleep (ev_tstamp delay) EV_THROW
1913
1944
  EV_TS_SET (ts, delay);
1914
1945
  nanosleep (&ts, 0);
1915
1946
  #elif defined _WIN32
1947
+ /* maybe this should round up, as ms is very low resolution */
1948
+ /* compared to select (µs) or nanosleep (ns) */
1916
1949
  Sleep ((unsigned long)(delay * 1e3));
1917
1950
  #else
1918
1951
  struct timeval tv;
@@ -1961,8 +1994,10 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1961
1994
  return ev_realloc (base, elem * *cur);
1962
1995
  }
1963
1996
 
1964
- #define array_init_zero(base,count) \
1965
- memset ((void *)(base), 0, sizeof (*(base)) * (count))
1997
+ #define array_needsize_noinit(base,offset,count)
1998
+
1999
+ #define array_needsize_zerofill(base,offset,count) \
2000
+ memset ((void *)(base + offset), 0, sizeof (*(base)) * (count))
1966
2001
 
1967
2002
  #define array_needsize(type,base,cur,cnt,init) \
1968
2003
  if (expect_false ((cnt) > (cur))) \
@@ -1970,7 +2005,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
1970
2005
  ecb_unused int ocur_ = (cur); \
1971
2006
  (base) = (type *)array_realloc \
1972
2007
  (sizeof (type), (base), &(cur), (cnt)); \
1973
- init ((base) + (ocur_), (cur) - ocur_); \
2008
+ init ((base), ocur_, ((cur) - ocur_)); \
1974
2009
  }
1975
2010
 
1976
2011
  #if 0
@@ -1997,7 +2032,7 @@ pendingcb (EV_P_ ev_prepare *w, int revents)
1997
2032
 
1998
2033
  noinline
1999
2034
  void
2000
- ev_feed_event (EV_P_ void *w, int revents) EV_THROW
2035
+ ev_feed_event (EV_P_ void *w, int revents) EV_NOEXCEPT
2001
2036
  {
2002
2037
  W w_ = (W)w;
2003
2038
  int pri = ABSPRI (w_);
@@ -2007,7 +2042,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_THROW
2007
2042
  else
2008
2043
  {
2009
2044
  w_->pending = ++pendingcnt [pri];
2010
- array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);
2045
+ array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, array_needsize_noinit);
2011
2046
  pendings [pri][w_->pending - 1].w = w_;
2012
2047
  pendings [pri][w_->pending - 1].events = revents;
2013
2048
  }
@@ -2018,7 +2053,7 @@ ev_feed_event (EV_P_ void *w, int revents) EV_THROW
2018
2053
  inline_speed void
2019
2054
  feed_reverse (EV_P_ W w)
2020
2055
  {
2021
- array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2);
2056
+ array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, array_needsize_noinit);
2022
2057
  rfeeds [rfeedcnt++] = w;
2023
2058
  }
2024
2059
 
@@ -2068,7 +2103,7 @@ fd_event (EV_P_ int fd, int revents)
2068
2103
  }
2069
2104
 
2070
2105
  void
2071
- ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW
2106
+ ev_feed_fd_event (EV_P_ int fd, int revents) EV_NOEXCEPT
2072
2107
  {
2073
2108
  if (fd >= 0 && fd < anfdmax)
2074
2109
  fd_event_nocheck (EV_A_ fd, revents);
@@ -2115,7 +2150,7 @@ fd_reify (EV_P)
2115
2150
  unsigned char o_events = anfd->events;
2116
2151
  unsigned char o_reify = anfd->reify;
2117
2152
 
2118
- anfd->reify = 0;
2153
+ anfd->reify = 0;
2119
2154
 
2120
2155
  /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */
2121
2156
  {
@@ -2146,7 +2181,7 @@ fd_change (EV_P_ int fd, int flags)
2146
2181
  if (expect_true (!reify))
2147
2182
  {
2148
2183
  ++fdchangecnt;
2149
- array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
2184
+ array_needsize (int, fdchanges, fdchangemax, fdchangecnt, array_needsize_noinit);
2150
2185
  fdchanges [fdchangecnt - 1] = fd;
2151
2186
  }
2152
2187
  }
@@ -2478,7 +2513,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag)
2478
2513
  #ifdef _WIN32
2479
2514
  WSABUF buf;
2480
2515
  DWORD sent;
2481
- buf.buf = &buf;
2516
+ buf.buf = (char *)&buf;
2482
2517
  buf.len = 1;
2483
2518
  WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
2484
2519
  #else
@@ -2560,7 +2595,7 @@ pipecb (EV_P_ ev_io *iow, int revents)
2560
2595
  /*****************************************************************************/
2561
2596
 
2562
2597
  void
2563
- ev_feed_signal (int signum) EV_THROW
2598
+ ev_feed_signal (int signum) EV_NOEXCEPT
2564
2599
  {
2565
2600
  #if EV_MULTIPLICITY
2566
2601
  EV_P;
@@ -2587,7 +2622,7 @@ ev_sighandler (int signum)
2587
2622
 
2588
2623
  noinline
2589
2624
  void
2590
- ev_feed_signal_event (EV_P_ int signum) EV_THROW
2625
+ ev_feed_signal_event (EV_P_ int signum) EV_NOEXCEPT
2591
2626
  {
2592
2627
  WL w;
2593
2628
 
@@ -2706,6 +2741,9 @@ childcb (EV_P_ ev_signal *sw, int revents)
2706
2741
  #if EV_USE_EPOLL
2707
2742
  # include "ev_epoll.c"
2708
2743
  #endif
2744
+ #if EV_USE_LINUXAIO
2745
+ # include "ev_linuxaio.c"
2746
+ #endif
2709
2747
  #if EV_USE_POLL
2710
2748
  # include "ev_poll.c"
2711
2749
  #endif
@@ -2714,13 +2752,13 @@ childcb (EV_P_ ev_signal *sw, int revents)
2714
2752
  #endif
2715
2753
 
2716
2754
  ecb_cold int
2717
- ev_version_major (void) EV_THROW
2755
+ ev_version_major (void) EV_NOEXCEPT
2718
2756
  {
2719
2757
  return EV_VERSION_MAJOR;
2720
2758
  }
2721
2759
 
2722
2760
  ecb_cold int
2723
- ev_version_minor (void) EV_THROW
2761
+ ev_version_minor (void) EV_NOEXCEPT
2724
2762
  {
2725
2763
  return EV_VERSION_MINOR;
2726
2764
  }
@@ -2739,45 +2777,56 @@ enable_secure (void)
2739
2777
 
2740
2778
  ecb_cold
2741
2779
  unsigned int
2742
- ev_supported_backends (void) EV_THROW
2780
+ ev_supported_backends (void) EV_NOEXCEPT
2743
2781
  {
2744
2782
  unsigned int flags = 0;
2745
2783
 
2746
- if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2747
- if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
2748
- if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2749
- if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2750
- if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
2784
+ if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
2785
+ if (EV_USE_KQUEUE ) flags |= EVBACKEND_KQUEUE;
2786
+ if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
2787
+
2788
+ #ifdef EV_USE_LINUXAIO
2789
+ if (EV_USE_LINUXAIO) flags |= EVBACKEND_LINUXAIO;
2790
+ #endif
2791
+
2792
+ if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
2793
+ if (EV_USE_SELECT ) flags |= EVBACKEND_SELECT;
2751
2794
 
2752
2795
  return flags;
2753
2796
  }
2754
2797
 
2755
2798
  ecb_cold
2756
2799
  unsigned int
2757
- ev_recommended_backends (void) EV_THROW
2800
+ ev_recommended_backends (void) EV_NOEXCEPT
2758
2801
  {
2759
2802
  unsigned int flags = ev_supported_backends ();
2760
2803
 
2761
- #ifndef __NetBSD__
2804
+ #if defined(__APPLE__) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14)
2805
+ /* apple has a poor track record but post 10.12.2 it seems to work sufficiently well */
2806
+ #elif defined(__NetBSD__)
2762
2807
  /* kqueue is borked on everything but netbsd apparently */
2763
2808
  /* it usually doesn't work correctly on anything but sockets and pipes */
2764
- flags &= ~EVBACKEND_KQUEUE;
2765
- #endif
2766
- #ifdef __APPLE__
2809
+ #else
2767
2810
  /* only select works correctly on that "unix-certified" platform */
2768
2811
  flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */
2769
2812
  flags &= ~EVBACKEND_POLL; /* poll is based on kqueue from 10.5 onwards */
2770
2813
  #endif
2814
+
2771
2815
  #ifdef __FreeBSD__
2772
2816
  flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */
2773
2817
  #endif
2774
2818
 
2819
+ /* TODO: linuxaio is very experimental */
2820
+ #if !EV_RECOMMEND_LINUXAIO
2821
+ flags &= ~EVBACKEND_LINUXAIO;
2822
+ #endif
2823
+
2775
2824
  return flags;
2776
2825
  }
2777
2826
 
2778
2827
  ecb_cold
2779
2828
  unsigned int
2780
- ev_embeddable_backends (void) EV_THROW
2829
+ ev_embeddable_backends (void) EV_NOEXCEPT
2781
2830
  {
2782
2831
  int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
2783
2832
 
@@ -2789,56 +2838,56 @@ ev_embeddable_backends (void) EV_THROW
2789
2838
  }
2790
2839
 
2791
2840
  unsigned int
2792
- ev_backend (EV_P) EV_THROW
2841
+ ev_backend (EV_P) EV_NOEXCEPT
2793
2842
  {
2794
2843
  return backend;
2795
2844
  }
2796
2845
 
2797
2846
  #if EV_FEATURE_API
2798
2847
  unsigned int
2799
- ev_iteration (EV_P) EV_THROW
2848
+ ev_iteration (EV_P) EV_NOEXCEPT
2800
2849
  {
2801
2850
  return loop_count;
2802
2851
  }
2803
2852
 
2804
2853
  unsigned int
2805
- ev_depth (EV_P) EV_THROW
2854
+ ev_depth (EV_P) EV_NOEXCEPT
2806
2855
  {
2807
2856
  return loop_depth;
2808
2857
  }
2809
2858
 
2810
2859
  void
2811
- ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
2860
+ ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT
2812
2861
  {
2813
2862
  io_blocktime = interval;
2814
2863
  }
2815
2864
 
2816
2865
  void
2817
- ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
2866
+ ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_NOEXCEPT
2818
2867
  {
2819
2868
  timeout_blocktime = interval;
2820
2869
  }
2821
2870
 
2822
2871
  void
2823
- ev_set_userdata (EV_P_ void *data) EV_THROW
2872
+ ev_set_userdata (EV_P_ void *data) EV_NOEXCEPT
2824
2873
  {
2825
2874
  userdata = data;
2826
2875
  }
2827
2876
 
2828
2877
  void *
2829
- ev_userdata (EV_P) EV_THROW
2878
+ ev_userdata (EV_P) EV_NOEXCEPT
2830
2879
  {
2831
2880
  return userdata;
2832
2881
  }
2833
2882
 
2834
2883
  void
2835
- ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW
2884
+ ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_NOEXCEPT
2836
2885
  {
2837
2886
  invoke_cb = invoke_pending_cb;
2838
2887
  }
2839
2888
 
2840
2889
  void
2841
- ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW
2890
+ ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_NOEXCEPT, void (*acquire)(EV_P) EV_NOEXCEPT) EV_NOEXCEPT
2842
2891
  {
2843
2892
  release_cb = release;
2844
2893
  acquire_cb = acquire;
@@ -2848,7 +2897,7 @@ ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV
2848
2897
  /* initialise a loop structure, must be zero-initialised */
2849
2898
  noinline ecb_cold
2850
2899
  static void
2851
- loop_init (EV_P_ unsigned int flags) EV_THROW
2900
+ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
2852
2901
  {
2853
2902
  if (!backend)
2854
2903
  {
@@ -2916,22 +2965,25 @@ loop_init (EV_P_ unsigned int flags) EV_THROW
2916
2965
  flags |= ev_recommended_backends ();
2917
2966
 
2918
2967
  #if EV_USE_IOCP
2919
- if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2968
+ if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
2920
2969
  #endif
2921
2970
  #if EV_USE_PORT
2922
- if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2971
+ if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
2923
2972
  #endif
2924
2973
  #if EV_USE_KQUEUE
2925
- if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
2974
+ if (!backend && (flags & EVBACKEND_KQUEUE )) backend = kqueue_init (EV_A_ flags);
2975
+ #endif
2976
+ #if EV_USE_LINUXAIO
2977
+ if (!backend && (flags & EVBACKEND_LINUXAIO)) backend = linuxaio_init (EV_A_ flags);
2926
2978
  #endif
2927
2979
  #if EV_USE_EPOLL
2928
- if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2980
+ if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
2929
2981
  #endif
2930
2982
  #if EV_USE_POLL
2931
- if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2983
+ if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
2932
2984
  #endif
2933
2985
  #if EV_USE_SELECT
2934
- if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
2986
+ if (!backend && (flags & EVBACKEND_SELECT )) backend = select_init (EV_A_ flags);
2935
2987
  #endif
2936
2988
 
2937
2989
  ev_prepare_init (&pending_w, pendingcb);
@@ -2996,22 +3048,25 @@ ev_loop_destroy (EV_P)
2996
3048
  close (backend_fd);
2997
3049
 
2998
3050
  #if EV_USE_IOCP
2999
- if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3051
+ if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
3000
3052
  #endif
3001
3053
  #if EV_USE_PORT
3002
- if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3054
+ if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
3003
3055
  #endif
3004
3056
  #if EV_USE_KQUEUE
3005
- if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
3057
+ if (backend == EVBACKEND_KQUEUE ) kqueue_destroy (EV_A);
3058
+ #endif
3059
+ #if EV_USE_LINUXAIO
3060
+ if (backend == EVBACKEND_LINUXAIO) linuxaio_destroy (EV_A);
3006
3061
  #endif
3007
3062
  #if EV_USE_EPOLL
3008
- if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3063
+ if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
3009
3064
  #endif
3010
3065
  #if EV_USE_POLL
3011
- if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3066
+ if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
3012
3067
  #endif
3013
3068
  #if EV_USE_SELECT
3014
- if (backend == EVBACKEND_SELECT) select_destroy (EV_A);
3069
+ if (backend == EVBACKEND_SELECT ) select_destroy (EV_A);
3015
3070
  #endif
3016
3071
 
3017
3072
  for (i = NUMPRI; i--; )
@@ -3063,13 +3118,16 @@ inline_size void
3063
3118
  loop_fork (EV_P)
3064
3119
  {
3065
3120
  #if EV_USE_PORT
3066
- if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3121
+ if (backend == EVBACKEND_PORT ) port_fork (EV_A);
3067
3122
  #endif
3068
3123
  #if EV_USE_KQUEUE
3069
- if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);
3124
+ if (backend == EVBACKEND_KQUEUE ) kqueue_fork (EV_A);
3125
+ #endif
3126
+ #if EV_USE_LINUXAIO
3127
+ if (backend == EVBACKEND_LINUXAIO) linuxaio_fork (EV_A);
3070
3128
  #endif
3071
3129
  #if EV_USE_EPOLL
3072
- if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3130
+ if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
3073
3131
  #endif
3074
3132
  #if EV_USE_INOTIFY
3075
3133
  infy_fork (EV_A);
@@ -3099,7 +3157,7 @@ loop_fork (EV_P)
3099
3157
 
3100
3158
  ecb_cold
3101
3159
  struct ev_loop *
3102
- ev_loop_new (unsigned int flags) EV_THROW
3160
+ ev_loop_new (unsigned int flags) EV_NOEXCEPT
3103
3161
  {
3104
3162
  EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
3105
3163
 
@@ -3156,7 +3214,7 @@ array_verify (EV_P_ W *ws, int cnt)
3156
3214
 
3157
3215
  #if EV_FEATURE_API
3158
3216
  void ecb_cold
3159
- ev_verify (EV_P) EV_THROW
3217
+ ev_verify (EV_P) EV_NOEXCEPT
3160
3218
  {
3161
3219
  #if EV_VERIFY
3162
3220
  int i;
@@ -3247,7 +3305,7 @@ struct ev_loop *
3247
3305
  #else
3248
3306
  int
3249
3307
  #endif
3250
- ev_default_loop (unsigned int flags) EV_THROW
3308
+ ev_default_loop (unsigned int flags) EV_NOEXCEPT
3251
3309
  {
3252
3310
  if (!ev_default_loop_ptr)
3253
3311
  {
@@ -3276,7 +3334,7 @@ ev_default_loop (unsigned int flags) EV_THROW
3276
3334
  }
3277
3335
 
3278
3336
  void
3279
- ev_loop_fork (EV_P) EV_THROW
3337
+ ev_loop_fork (EV_P) EV_NOEXCEPT
3280
3338
  {
3281
3339
  postfork = 1;
3282
3340
  }
@@ -3290,7 +3348,7 @@ ev_invoke (EV_P_ void *w, int revents)
3290
3348
  }
3291
3349
 
3292
3350
  unsigned int
3293
- ev_pending_count (EV_P) EV_THROW
3351
+ ev_pending_count (EV_P) EV_NOEXCEPT
3294
3352
  {
3295
3353
  int pri;
3296
3354
  unsigned int count = 0;
@@ -3307,10 +3365,11 @@ ev_invoke_pending (EV_P)
3307
3365
  {
3308
3366
  pendingpri = NUMPRI;
3309
3367
 
3310
- while (pendingpri) /* pendingpri possibly gets modified in the inner loop */
3368
+ do
3311
3369
  {
3312
3370
  --pendingpri;
3313
3371
 
3372
+ /* pendingpri possibly gets modified in the inner loop */
3314
3373
  while (pendingcnt [pendingpri])
3315
3374
  {
3316
3375
  ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];
@@ -3320,6 +3379,7 @@ ev_invoke_pending (EV_P)
3320
3379
  EV_FREQUENT_CHECK;
3321
3380
  }
3322
3381
  }
3382
+ while (pendingpri);
3323
3383
  }
3324
3384
 
3325
3385
  #if EV_IDLE_ENABLE
@@ -3572,11 +3632,13 @@ struct ev_poll_args {
3572
3632
  };
3573
3633
 
3574
3634
  static
3575
- VALUE ev_backend_poll(void *ptr)
3635
+ void * ev_backend_poll(void *ptr)
3576
3636
  {
3577
3637
  struct ev_poll_args *args = (struct ev_poll_args *)ptr;
3578
3638
  struct ev_loop *loop = args->loop;
3579
3639
  backend_poll (EV_A_ args->waittime);
3640
+
3641
+ return NULL;
3580
3642
  }
3581
3643
  /* ######################################## */
3582
3644
 
@@ -3584,7 +3646,7 @@ int
3584
3646
  ev_run (EV_P_ int flags)
3585
3647
  {
3586
3648
  /* ########## NIO4R PATCHERY HO! ########## */
3587
- struct ev_poll_args poll_args;
3649
+ struct ev_poll_args poll_args;
3588
3650
  /* ######################################## */
3589
3651
 
3590
3652
  #if EV_FEATURE_API
@@ -3804,37 +3866,37 @@ rb_thread_unsafe_dangerous_crazy_blocking_region_end(...);
3804
3866
  }
3805
3867
 
3806
3868
  void
3807
- ev_break (EV_P_ int how) EV_THROW
3869
+ ev_break (EV_P_ int how) EV_NOEXCEPT
3808
3870
  {
3809
3871
  loop_done = how;
3810
3872
  }
3811
3873
 
3812
3874
  void
3813
- ev_ref (EV_P) EV_THROW
3875
+ ev_ref (EV_P) EV_NOEXCEPT
3814
3876
  {
3815
3877
  ++activecnt;
3816
3878
  }
3817
3879
 
3818
3880
  void
3819
- ev_unref (EV_P) EV_THROW
3881
+ ev_unref (EV_P) EV_NOEXCEPT
3820
3882
  {
3821
3883
  --activecnt;
3822
3884
  }
3823
3885
 
3824
3886
  void
3825
- ev_now_update (EV_P) EV_THROW
3887
+ ev_now_update (EV_P) EV_NOEXCEPT
3826
3888
  {
3827
3889
  time_update (EV_A_ 1e100);
3828
3890
  }
3829
3891
 
3830
3892
  void
3831
- ev_suspend (EV_P) EV_THROW
3893
+ ev_suspend (EV_P) EV_NOEXCEPT
3832
3894
  {
3833
3895
  ev_now_update (EV_A);
3834
3896
  }
3835
3897
 
3836
3898
  void
3837
- ev_resume (EV_P) EV_THROW
3899
+ ev_resume (EV_P) EV_NOEXCEPT
3838
3900
  {
3839
3901
  ev_tstamp mn_prev = mn_now;
3840
3902
 
@@ -3883,7 +3945,7 @@ clear_pending (EV_P_ W w)
3883
3945
  }
3884
3946
 
3885
3947
  int
3886
- ev_clear_pending (EV_P_ void *w) EV_THROW
3948
+ ev_clear_pending (EV_P_ void *w) EV_NOEXCEPT
3887
3949
  {
3888
3950
  W w_ = (W)w;
3889
3951
  int pending = w_->pending;
@@ -3927,7 +3989,7 @@ ev_stop (EV_P_ W w)
3927
3989
 
3928
3990
  noinline
3929
3991
  void
3930
- ev_io_start (EV_P_ ev_io *w) EV_THROW
3992
+ ev_io_start (EV_P_ ev_io *w) EV_NOEXCEPT
3931
3993
  {
3932
3994
  int fd = w->fd;
3933
3995
 
@@ -3937,10 +3999,13 @@ ev_io_start (EV_P_ ev_io *w) EV_THROW
3937
3999
  assert (("libev: ev_io_start called with negative fd", fd >= 0));
3938
4000
  assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE))));
3939
4001
 
4002
+ #if EV_VERIFY >= 2
4003
+ assert (("libev: ev_io_start called on watcher with invalid fd", fd_valid (fd)));
4004
+ #endif
3940
4005
  EV_FREQUENT_CHECK;
3941
4006
 
3942
4007
  ev_start (EV_A_ (W)w, 1);
3943
- array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
4008
+ array_needsize (ANFD, anfds, anfdmax, fd + 1, array_needsize_zerofill);
3944
4009
  wlist_add (&anfds[fd].head, (WL)w);
3945
4010
 
3946
4011
  /* common bug, apparently */
@@ -3954,7 +4019,7 @@ ev_io_start (EV_P_ ev_io *w) EV_THROW
3954
4019
 
3955
4020
  noinline
3956
4021
  void
3957
- ev_io_stop (EV_P_ ev_io *w) EV_THROW
4022
+ ev_io_stop (EV_P_ ev_io *w) EV_NOEXCEPT
3958
4023
  {
3959
4024
  clear_pending (EV_A_ (W)w);
3960
4025
  if (expect_false (!ev_is_active (w)))
@@ -3962,6 +4027,9 @@ ev_io_stop (EV_P_ ev_io *w) EV_THROW
3962
4027
 
3963
4028
  assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax));
3964
4029
 
4030
+ #if EV_VERIFY >= 2
4031
+ assert (("libev: ev_io_stop called on watcher with invalid fd", fd_valid (w->fd)));
4032
+ #endif
3965
4033
  EV_FREQUENT_CHECK;
3966
4034
 
3967
4035
  wlist_del (&anfds[w->fd].head, (WL)w);
@@ -3974,7 +4042,7 @@ ev_io_stop (EV_P_ ev_io *w) EV_THROW
3974
4042
 
3975
4043
  noinline
3976
4044
  void
3977
- ev_timer_start (EV_P_ ev_timer *w) EV_THROW
4045
+ ev_timer_start (EV_P_ ev_timer *w) EV_NOEXCEPT
3978
4046
  {
3979
4047
  if (expect_false (ev_is_active (w)))
3980
4048
  return;
@@ -3987,7 +4055,7 @@ ev_timer_start (EV_P_ ev_timer *w) EV_THROW
3987
4055
 
3988
4056
  ++timercnt;
3989
4057
  ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);
3990
- array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);
4058
+ array_needsize (ANHE, timers, timermax, ev_active (w) + 1, array_needsize_noinit);
3991
4059
  ANHE_w (timers [ev_active (w)]) = (WT)w;
3992
4060
  ANHE_at_cache (timers [ev_active (w)]);
3993
4061
  upheap (timers, ev_active (w));
@@ -3999,7 +4067,7 @@ ev_timer_start (EV_P_ ev_timer *w) EV_THROW
3999
4067
 
4000
4068
  noinline
4001
4069
  void
4002
- ev_timer_stop (EV_P_ ev_timer *w) EV_THROW
4070
+ ev_timer_stop (EV_P_ ev_timer *w) EV_NOEXCEPT
4003
4071
  {
4004
4072
  clear_pending (EV_A_ (W)w);
4005
4073
  if (expect_false (!ev_is_active (w)))
@@ -4030,7 +4098,7 @@ ev_timer_stop (EV_P_ ev_timer *w) EV_THROW
4030
4098
 
4031
4099
  noinline
4032
4100
  void
4033
- ev_timer_again (EV_P_ ev_timer *w) EV_THROW
4101
+ ev_timer_again (EV_P_ ev_timer *w) EV_NOEXCEPT
4034
4102
  {
4035
4103
  EV_FREQUENT_CHECK;
4036
4104
 
@@ -4057,7 +4125,7 @@ ev_timer_again (EV_P_ ev_timer *w) EV_THROW
4057
4125
  }
4058
4126
 
4059
4127
  ev_tstamp
4060
- ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW
4128
+ ev_timer_remaining (EV_P_ ev_timer *w) EV_NOEXCEPT
4061
4129
  {
4062
4130
  return ev_at (w) - (ev_is_active (w) ? mn_now : 0.);
4063
4131
  }
@@ -4065,7 +4133,7 @@ ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW
4065
4133
  #if EV_PERIODIC_ENABLE
4066
4134
  noinline
4067
4135
  void
4068
- ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
4136
+ ev_periodic_start (EV_P_ ev_periodic *w) EV_NOEXCEPT
4069
4137
  {
4070
4138
  if (expect_false (ev_is_active (w)))
4071
4139
  return;
@@ -4084,7 +4152,7 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
4084
4152
 
4085
4153
  ++periodiccnt;
4086
4154
  ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1);
4087
- array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2);
4155
+ array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, array_needsize_noinit);
4088
4156
  ANHE_w (periodics [ev_active (w)]) = (WT)w;
4089
4157
  ANHE_at_cache (periodics [ev_active (w)]);
4090
4158
  upheap (periodics, ev_active (w));
@@ -4096,7 +4164,7 @@ ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
4096
4164
 
4097
4165
  noinline
4098
4166
  void
4099
- ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW
4167
+ ev_periodic_stop (EV_P_ ev_periodic *w) EV_NOEXCEPT
4100
4168
  {
4101
4169
  clear_pending (EV_A_ (W)w);
4102
4170
  if (expect_false (!ev_is_active (w)))
@@ -4125,7 +4193,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW
4125
4193
 
4126
4194
  noinline
4127
4195
  void
4128
- ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW
4196
+ ev_periodic_again (EV_P_ ev_periodic *w) EV_NOEXCEPT
4129
4197
  {
4130
4198
  /* TODO: use adjustheap and recalculation */
4131
4199
  ev_periodic_stop (EV_A_ w);
@@ -4141,7 +4209,7 @@ ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW
4141
4209
 
4142
4210
  noinline
4143
4211
  void
4144
- ev_signal_start (EV_P_ ev_signal *w) EV_THROW
4212
+ ev_signal_start (EV_P_ ev_signal *w) EV_NOEXCEPT
4145
4213
  {
4146
4214
  if (expect_false (ev_is_active (w)))
4147
4215
  return;
@@ -4224,7 +4292,7 @@ ev_signal_start (EV_P_ ev_signal *w) EV_THROW
4224
4292
 
4225
4293
  noinline
4226
4294
  void
4227
- ev_signal_stop (EV_P_ ev_signal *w) EV_THROW
4295
+ ev_signal_stop (EV_P_ ev_signal *w) EV_NOEXCEPT
4228
4296
  {
4229
4297
  clear_pending (EV_A_ (W)w);
4230
4298
  if (expect_false (!ev_is_active (w)))
@@ -4265,7 +4333,7 @@ ev_signal_stop (EV_P_ ev_signal *w) EV_THROW
4265
4333
  #if EV_CHILD_ENABLE
4266
4334
 
4267
4335
  void
4268
- ev_child_start (EV_P_ ev_child *w) EV_THROW
4336
+ ev_child_start (EV_P_ ev_child *w) EV_NOEXCEPT
4269
4337
  {
4270
4338
  #if EV_MULTIPLICITY
4271
4339
  assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
@@ -4282,7 +4350,7 @@ ev_child_start (EV_P_ ev_child *w) EV_THROW
4282
4350
  }
4283
4351
 
4284
4352
  void
4285
- ev_child_stop (EV_P_ ev_child *w) EV_THROW
4353
+ ev_child_stop (EV_P_ ev_child *w) EV_NOEXCEPT
4286
4354
  {
4287
4355
  clear_pending (EV_A_ (W)w);
4288
4356
  if (expect_false (!ev_is_active (w)))
@@ -4557,7 +4625,7 @@ infy_fork (EV_P)
4557
4625
  #endif
4558
4626
 
4559
4627
  void
4560
- ev_stat_stat (EV_P_ ev_stat *w) EV_THROW
4628
+ ev_stat_stat (EV_P_ ev_stat *w) EV_NOEXCEPT
4561
4629
  {
4562
4630
  if (lstat (w->path, &w->attr) < 0)
4563
4631
  w->attr.st_nlink = 0;
@@ -4607,7 +4675,7 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
4607
4675
  }
4608
4676
 
4609
4677
  void
4610
- ev_stat_start (EV_P_ ev_stat *w) EV_THROW
4678
+ ev_stat_start (EV_P_ ev_stat *w) EV_NOEXCEPT
4611
4679
  {
4612
4680
  if (expect_false (ev_is_active (w)))
4613
4681
  return;
@@ -4638,7 +4706,7 @@ ev_stat_start (EV_P_ ev_stat *w) EV_THROW
4638
4706
  }
4639
4707
 
4640
4708
  void
4641
- ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
4709
+ ev_stat_stop (EV_P_ ev_stat *w) EV_NOEXCEPT
4642
4710
  {
4643
4711
  clear_pending (EV_A_ (W)w);
4644
4712
  if (expect_false (!ev_is_active (w)))
@@ -4664,7 +4732,7 @@ ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
4664
4732
 
4665
4733
  #if EV_IDLE_ENABLE
4666
4734
  void
4667
- ev_idle_start (EV_P_ ev_idle *w) EV_THROW
4735
+ ev_idle_start (EV_P_ ev_idle *w) EV_NOEXCEPT
4668
4736
  {
4669
4737
  if (expect_false (ev_is_active (w)))
4670
4738
  return;
@@ -4679,7 +4747,7 @@ ev_idle_start (EV_P_ ev_idle *w) EV_THROW
4679
4747
  ++idleall;
4680
4748
  ev_start (EV_A_ (W)w, active);
4681
4749
 
4682
- array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2);
4750
+ array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, array_needsize_noinit);
4683
4751
  idles [ABSPRI (w)][active - 1] = w;
4684
4752
  }
4685
4753
 
@@ -4687,7 +4755,7 @@ ev_idle_start (EV_P_ ev_idle *w) EV_THROW
4687
4755
  }
4688
4756
 
4689
4757
  void
4690
- ev_idle_stop (EV_P_ ev_idle *w) EV_THROW
4758
+ ev_idle_stop (EV_P_ ev_idle *w) EV_NOEXCEPT
4691
4759
  {
4692
4760
  clear_pending (EV_A_ (W)w);
4693
4761
  if (expect_false (!ev_is_active (w)))
@@ -4711,7 +4779,7 @@ ev_idle_stop (EV_P_ ev_idle *w) EV_THROW
4711
4779
 
4712
4780
  #if EV_PREPARE_ENABLE
4713
4781
  void
4714
- ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW
4782
+ ev_prepare_start (EV_P_ ev_prepare *w) EV_NOEXCEPT
4715
4783
  {
4716
4784
  if (expect_false (ev_is_active (w)))
4717
4785
  return;
@@ -4719,14 +4787,14 @@ ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW
4719
4787
  EV_FREQUENT_CHECK;
4720
4788
 
4721
4789
  ev_start (EV_A_ (W)w, ++preparecnt);
4722
- array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2);
4790
+ array_needsize (ev_prepare *, prepares, preparemax, preparecnt, array_needsize_noinit);
4723
4791
  prepares [preparecnt - 1] = w;
4724
4792
 
4725
4793
  EV_FREQUENT_CHECK;
4726
4794
  }
4727
4795
 
4728
4796
  void
4729
- ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW
4797
+ ev_prepare_stop (EV_P_ ev_prepare *w) EV_NOEXCEPT
4730
4798
  {
4731
4799
  clear_pending (EV_A_ (W)w);
4732
4800
  if (expect_false (!ev_is_active (w)))
@@ -4749,7 +4817,7 @@ ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW
4749
4817
 
4750
4818
  #if EV_CHECK_ENABLE
4751
4819
  void
4752
- ev_check_start (EV_P_ ev_check *w) EV_THROW
4820
+ ev_check_start (EV_P_ ev_check *w) EV_NOEXCEPT
4753
4821
  {
4754
4822
  if (expect_false (ev_is_active (w)))
4755
4823
  return;
@@ -4757,14 +4825,14 @@ ev_check_start (EV_P_ ev_check *w) EV_THROW
4757
4825
  EV_FREQUENT_CHECK;
4758
4826
 
4759
4827
  ev_start (EV_A_ (W)w, ++checkcnt);
4760
- array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2);
4828
+ array_needsize (ev_check *, checks, checkmax, checkcnt, array_needsize_noinit);
4761
4829
  checks [checkcnt - 1] = w;
4762
4830
 
4763
4831
  EV_FREQUENT_CHECK;
4764
4832
  }
4765
4833
 
4766
4834
  void
4767
- ev_check_stop (EV_P_ ev_check *w) EV_THROW
4835
+ ev_check_stop (EV_P_ ev_check *w) EV_NOEXCEPT
4768
4836
  {
4769
4837
  clear_pending (EV_A_ (W)w);
4770
4838
  if (expect_false (!ev_is_active (w)))
@@ -4788,7 +4856,7 @@ ev_check_stop (EV_P_ ev_check *w) EV_THROW
4788
4856
  #if EV_EMBED_ENABLE
4789
4857
  noinline
4790
4858
  void
4791
- ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW
4859
+ ev_embed_sweep (EV_P_ ev_embed *w) EV_NOEXCEPT
4792
4860
  {
4793
4861
  ev_run (w->other, EVRUN_NOWAIT);
4794
4862
  }
@@ -4846,7 +4914,7 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
4846
4914
  #endif
4847
4915
 
4848
4916
  void
4849
- ev_embed_start (EV_P_ ev_embed *w) EV_THROW
4917
+ ev_embed_start (EV_P_ ev_embed *w) EV_NOEXCEPT
4850
4918
  {
4851
4919
  if (expect_false (ev_is_active (w)))
4852
4920
  return;
@@ -4877,7 +4945,7 @@ ev_embed_start (EV_P_ ev_embed *w) EV_THROW
4877
4945
  }
4878
4946
 
4879
4947
  void
4880
- ev_embed_stop (EV_P_ ev_embed *w) EV_THROW
4948
+ ev_embed_stop (EV_P_ ev_embed *w) EV_NOEXCEPT
4881
4949
  {
4882
4950
  clear_pending (EV_A_ (W)w);
4883
4951
  if (expect_false (!ev_is_active (w)))
@@ -4897,7 +4965,7 @@ ev_embed_stop (EV_P_ ev_embed *w) EV_THROW
4897
4965
 
4898
4966
  #if EV_FORK_ENABLE
4899
4967
  void
4900
- ev_fork_start (EV_P_ ev_fork *w) EV_THROW
4968
+ ev_fork_start (EV_P_ ev_fork *w) EV_NOEXCEPT
4901
4969
  {
4902
4970
  if (expect_false (ev_is_active (w)))
4903
4971
  return;
@@ -4905,14 +4973,14 @@ ev_fork_start (EV_P_ ev_fork *w) EV_THROW
4905
4973
  EV_FREQUENT_CHECK;
4906
4974
 
4907
4975
  ev_start (EV_A_ (W)w, ++forkcnt);
4908
- array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2);
4976
+ array_needsize (ev_fork *, forks, forkmax, forkcnt, array_needsize_noinit);
4909
4977
  forks [forkcnt - 1] = w;
4910
4978
 
4911
4979
  EV_FREQUENT_CHECK;
4912
4980
  }
4913
4981
 
4914
4982
  void
4915
- ev_fork_stop (EV_P_ ev_fork *w) EV_THROW
4983
+ ev_fork_stop (EV_P_ ev_fork *w) EV_NOEXCEPT
4916
4984
  {
4917
4985
  clear_pending (EV_A_ (W)w);
4918
4986
  if (expect_false (!ev_is_active (w)))
@@ -4935,7 +5003,7 @@ ev_fork_stop (EV_P_ ev_fork *w) EV_THROW
4935
5003
 
4936
5004
  #if EV_CLEANUP_ENABLE
4937
5005
  void
4938
- ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
5006
+ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4939
5007
  {
4940
5008
  if (expect_false (ev_is_active (w)))
4941
5009
  return;
@@ -4943,7 +5011,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
4943
5011
  EV_FREQUENT_CHECK;
4944
5012
 
4945
5013
  ev_start (EV_A_ (W)w, ++cleanupcnt);
4946
- array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2);
5014
+ array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, array_needsize_noinit);
4947
5015
  cleanups [cleanupcnt - 1] = w;
4948
5016
 
4949
5017
  /* cleanup watchers should never keep a refcount on the loop */
@@ -4952,7 +5020,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
4952
5020
  }
4953
5021
 
4954
5022
  void
4955
- ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW
5023
+ ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_NOEXCEPT
4956
5024
  {
4957
5025
  clear_pending (EV_A_ (W)w);
4958
5026
  if (expect_false (!ev_is_active (w)))
@@ -4976,7 +5044,7 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW
4976
5044
 
4977
5045
  #if EV_ASYNC_ENABLE
4978
5046
  void
4979
- ev_async_start (EV_P_ ev_async *w) EV_THROW
5047
+ ev_async_start (EV_P_ ev_async *w) EV_NOEXCEPT
4980
5048
  {
4981
5049
  if (expect_false (ev_is_active (w)))
4982
5050
  return;
@@ -4988,14 +5056,14 @@ ev_async_start (EV_P_ ev_async *w) EV_THROW
4988
5056
  EV_FREQUENT_CHECK;
4989
5057
 
4990
5058
  ev_start (EV_A_ (W)w, ++asynccnt);
4991
- array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2);
5059
+ array_needsize (ev_async *, asyncs, asyncmax, asynccnt, array_needsize_noinit);
4992
5060
  asyncs [asynccnt - 1] = w;
4993
5061
 
4994
5062
  EV_FREQUENT_CHECK;
4995
5063
  }
4996
5064
 
4997
5065
  void
4998
- ev_async_stop (EV_P_ ev_async *w) EV_THROW
5066
+ ev_async_stop (EV_P_ ev_async *w) EV_NOEXCEPT
4999
5067
  {
5000
5068
  clear_pending (EV_A_ (W)w);
5001
5069
  if (expect_false (!ev_is_active (w)))
@@ -5016,7 +5084,7 @@ ev_async_stop (EV_P_ ev_async *w) EV_THROW
5016
5084
  }
5017
5085
 
5018
5086
  void
5019
- ev_async_send (EV_P_ ev_async *w) EV_THROW
5087
+ ev_async_send (EV_P_ ev_async *w) EV_NOEXCEPT
5020
5088
  {
5021
5089
  w->sent = 1;
5022
5090
  evpipe_write (EV_A_ &async_pending);
@@ -5063,16 +5131,10 @@ once_cb_to (EV_P_ ev_timer *w, int revents)
5063
5131
  }
5064
5132
 
5065
5133
  void
5066
- ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW
5134
+ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_NOEXCEPT
5067
5135
  {
5068
5136
  struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
5069
5137
 
5070
- if (expect_false (!once))
5071
- {
5072
- cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg);
5073
- return;
5074
- }
5075
-
5076
5138
  once->cb = cb;
5077
5139
  once->arg = arg;
5078
5140
 
@@ -5096,7 +5158,7 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
5096
5158
  #if EV_WALK_ENABLE
5097
5159
  ecb_cold
5098
5160
  void
5099
- ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW
5161
+ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_NOEXCEPT
5100
5162
  {
5101
5163
  int i, j;
5102
5164
  ev_watcher_list *wl, *wn;