polyphony 0.72 → 0.75

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +15 -11
  3. data/.github/workflows/test_io_uring.yml +32 -0
  4. data/.gitignore +3 -1
  5. data/CHANGELOG.md +24 -0
  6. data/Gemfile.lock +16 -13
  7. data/bin/pdbg +0 -0
  8. data/bin/polyphony-debug +0 -0
  9. data/bin/stress.rb +0 -0
  10. data/bin/test +0 -0
  11. data/docs/api-reference/exception.md +5 -1
  12. data/examples/core/ring.rb +29 -0
  13. data/ext/polyphony/backend_common.c +90 -12
  14. data/ext/polyphony/backend_common.h +9 -1
  15. data/ext/polyphony/backend_io_uring.c +257 -134
  16. data/ext/polyphony/backend_io_uring_context.c +1 -0
  17. data/ext/polyphony/backend_io_uring_context.h +2 -1
  18. data/ext/polyphony/backend_libev.c +33 -29
  19. data/ext/polyphony/event.c +5 -2
  20. data/ext/polyphony/extconf.rb +1 -0
  21. data/ext/polyphony/polyphony.c +11 -1
  22. data/ext/polyphony/polyphony.h +9 -2
  23. data/ext/polyphony/queue.c +10 -5
  24. data/ext/polyphony/runqueue_ring_buffer.c +3 -1
  25. data/ext/polyphony/socket_extensions.c +5 -2
  26. data/ext/polyphony/thread.c +1 -1
  27. data/lib/polyphony/{extensions → core}/debug.rb +0 -0
  28. data/lib/polyphony/core/global_api.rb +0 -3
  29. data/lib/polyphony/extensions/exception.rb +45 -0
  30. data/lib/polyphony/extensions/fiber.rb +85 -4
  31. data/lib/polyphony/extensions/{core.rb → kernel.rb} +0 -73
  32. data/lib/polyphony/extensions/openssl.rb +5 -1
  33. data/lib/polyphony/extensions/process.rb +19 -0
  34. data/lib/polyphony/extensions/socket.rb +12 -6
  35. data/lib/polyphony/extensions/thread.rb +9 -3
  36. data/lib/polyphony/extensions/timeout.rb +10 -0
  37. data/lib/polyphony/extensions.rb +9 -0
  38. data/lib/polyphony/version.rb +1 -1
  39. data/lib/polyphony.rb +4 -4
  40. data/test/helper.rb +0 -5
  41. data/test/test_backend.rb +3 -5
  42. data/test/test_global_api.rb +21 -12
  43. data/test/test_io.rb +2 -2
  44. data/test/test_kernel.rb +2 -2
  45. data/test/test_process_supervision.rb +1 -1
  46. data/test/test_signal.rb +20 -1
  47. data/test/test_socket.rb +35 -2
  48. data/test/test_thread.rb +1 -1
  49. data/test/test_thread_pool.rb +1 -1
  50. data/test/test_throttler.rb +3 -3
  51. data/test/test_timer.rb +1 -1
  52. data/test/test_trace.rb +7 -1
  53. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2af189faeecbe2eecb367a7400005306ab74370e56c61de1d703edd40d851d92
4
- data.tar.gz: c0888b10d03b9bf29f1d10a41b0050231db655c587d06035039b4c09e1c68baa
3
+ metadata.gz: 25015dd770af4d3b375af0625cfe9fe98becb328a0e77abb3101be2580279a7c
4
+ data.tar.gz: e2227ea3fa7d3ec04f5b580afdc92b9d7aacbab76b9e17dd0b86fb5e4e5b6a6f
5
5
  SHA512:
6
- metadata.gz: b86fd5682ce52e635658a8d620031f8ae841ef5f7876d6239f74772d8f700054eb3bb7732488e246433a91e5ab4279479c6f18bb0d1a154172d90f351ab8149e
7
- data.tar.gz: 713ba61a64ef73c5c16971bd0d678d6575b7bd37062a29348f02ec8e0578821d7ec41f826f1868cd017bede9c70d47192e19a0217469b331f17ff66afac21054
6
+ metadata.gz: 967f6aa30621aae39dafdb587c28e1c0ec96685fc82972adb19fb50de7adfaaa42ce861c0f941f85ad536e29b459251d22c34a6bd96f8fc89f23dd4c0ecac47a
7
+ data.tar.gz: b3d6884d859c4eb61ca1d8bc8d1b727a5bf66c6c1af5280896264414bf14654650a1d8bcf3a6b744d235f5dd435e9231a0e047f95a17bfb7ce1642791c347c05
@@ -7,25 +7,29 @@ jobs:
7
7
  strategy:
8
8
  fail-fast: false
9
9
  matrix:
10
- os: [ubuntu-latest, ubuntu-18.04, macos-10.15]
11
- ruby: [2.6, 2.7, 3.0]
10
+ os: [ubuntu-latest, macos-latest]
11
+ ruby: ['2.7', '3.0', '3.1', 'head']
12
12
 
13
13
  name: >-
14
14
  ${{matrix.os}}, ${{matrix.ruby}}
15
15
 
16
16
  runs-on: ${{matrix.os}}
17
+
18
+ env:
19
+ POLYPHONY_USE_LIBEV: "1"
20
+
17
21
  steps:
18
- - uses: actions/checkout@v1
19
- - uses: actions/setup-ruby@v1
22
+ - name: Setup OS
23
+ uses: actions/checkout@v1
24
+ - name: Setup Ruby
25
+ uses: ruby/setup-ruby@v1
20
26
  with:
21
27
  ruby-version: ${{matrix.ruby}}
22
- - name: Install dependencies
23
- run: |
24
- gem install bundler
25
- bundle install
26
- - name: Show Linux kernel version
27
- run: uname -r
28
+ bundler-cache: true # 'bundle install' and cache
29
+ cache-version: 2
30
+ - name: Kernel version
31
+ run: uname -a
28
32
  - name: Compile C-extension
29
- run: POLYPHONY_USE_LIBEV=1 bundle exec rake compile
33
+ run: bundle exec rake compile
30
34
  - name: Run tests
31
35
  run: bundle exec rake test
@@ -0,0 +1,32 @@
1
+ name: Tests with io_uring
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest]
11
+ ruby: [2.6, 2.7, 3.0]
12
+
13
+ name: >-
14
+ ${{matrix.os}}, ${{matrix.ruby}}
15
+
16
+ runs-on: ${{matrix.os}}
17
+ steps:
18
+ - uses: actions/checkout@v1
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{matrix.ruby}}
22
+ bundler-cache: true # 'bundle install' and cache
23
+ - name: Install dependencies
24
+ run: |
25
+ gem install bundler
26
+ bundle install
27
+ - name: Show Linux kernel version
28
+ run: uname -a
29
+ - name: Compile C-extension
30
+ run: bundle exec rake compile
31
+ - name: Run tests
32
+ run: bundle exec rake test
data/.gitignore CHANGED
@@ -58,4 +58,6 @@ lib/*.so
58
58
  _site
59
59
  .sass-cache
60
60
 
61
- log
61
+ log
62
+
63
+ .ruby-version
data/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ ## 0.75 2022-02-04
2
+
3
+ - Fix handling of MoveOn on main fiber of forked process
4
+ - Ensure SSLSocket underlying socket is in nonblocking mode
5
+ - Add `Polyphony.backend_verify_blocking_mode` API
6
+ - Fix address resolution for hostnames with IPv6 address
7
+ - Improve behaviour of OOB fiber
8
+ - Include caller in `fiber_switchpoint` trace
9
+
10
+ ## 0.74 2022-02-01
11
+
12
+ - Add support for IPv6 (#69)
13
+ - Override TCPSocket.open
14
+
15
+ ## 0.73.1 2021-12-17
16
+
17
+ - Fix Gemfile.lock
18
+
19
+ ## 0.73 2021-12-16
20
+
21
+ - Refactor core extensions into separate files for each class
22
+ - Improve compatibility with Ruby 3.1
23
+ - Improve accuracy of `timer_loop`
24
+
1
25
  ## 0.72 2021-11-22
2
26
 
3
27
  - Add support for supervising added child fibers
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.72)
4
+ polyphony (0.75)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -14,12 +14,12 @@ GEM
14
14
  httparty (0.17.1)
15
15
  mime-types (~> 3.0)
16
16
  multi_xml (>= 0.5.2)
17
- json (2.5.1)
18
- localhost (1.1.8)
17
+ json (2.6.1)
18
+ localhost (1.1.9)
19
19
  method_source (1.0.0)
20
- mime-types (3.3.1)
20
+ mime-types (3.4.1)
21
21
  mime-types-data (~> 3.2015)
22
- mime-types-data (3.2021.0704)
22
+ mime-types-data (3.2022.0105)
23
23
  minitest (5.14.4)
24
24
  minitest-reporters (1.4.2)
25
25
  ansi
@@ -28,17 +28,17 @@ GEM
28
28
  ruby-progressbar
29
29
  msgpack (1.4.2)
30
30
  multi_xml (0.6.0)
31
- parallel (1.20.1)
32
- parser (3.0.2.0)
31
+ parallel (1.21.0)
32
+ parser (3.1.0.0)
33
33
  ast (~> 2.4.1)
34
34
  pry (0.13.1)
35
35
  coderay (~> 1.1)
36
36
  method_source (~> 1.0)
37
- rainbow (3.0.0)
37
+ rainbow (3.1.1)
38
38
  rake (13.0.6)
39
39
  rake-compiler (1.1.1)
40
40
  rake
41
- regexp_parser (2.1.1)
41
+ regexp_parser (2.2.0)
42
42
  rexml (3.2.5)
43
43
  rubocop (0.85.1)
44
44
  parallel (~> 1.10)
@@ -49,7 +49,7 @@ GEM
49
49
  rubocop-ast (>= 0.0.3)
50
50
  ruby-progressbar (~> 1.7)
51
51
  unicode-display_width (>= 1.4.0, < 2.0)
52
- rubocop-ast (1.8.0)
52
+ rubocop-ast (1.15.1)
53
53
  parser (>= 3.0.1.1)
54
54
  ruby-progressbar (1.11.0)
55
55
  simplecov (0.17.1)
@@ -57,10 +57,13 @@ GEM
57
57
  json (>= 1.8, < 3)
58
58
  simplecov-html (~> 0.10.0)
59
59
  simplecov-html (0.10.2)
60
- unicode-display_width (1.7.0)
60
+ unicode-display_width (1.8.0)
61
61
 
62
62
  PLATFORMS
63
- ruby
63
+ universal-darwin
64
+ universal-freebsd
65
+ universal-linux
66
+ universal-unknown
64
67
 
65
68
  DEPENDENCIES
66
69
  httparty (= 0.17.1)
@@ -75,4 +78,4 @@ DEPENDENCIES
75
78
  simplecov (= 0.17.1)
76
79
 
77
80
  BUNDLED WITH
78
- 2.2.26
81
+ 2.3.3
data/bin/pdbg CHANGED
File without changes
data/bin/polyphony-debug CHANGED
File without changes
data/bin/stress.rb CHANGED
File without changes
data/bin/test CHANGED
File without changes
@@ -3,15 +3,19 @@ layout: page
3
3
  title: ::Exception
4
4
  parent: API Reference
5
5
  permalink: /api-reference/exception/
6
+ source_url: https://github.com/digital-fabric/polyphony/blob/master/lib/polyphony/extensions/core.rb
7
+ ruby_docs_url: https://rubyapi.org/3.0/o/exception
6
8
  ---
7
9
  # ::Exception
8
10
 
9
- [Ruby core Exception documentation](https://ruby-doc.org/core-2.7.0/Exception.html)
11
+ [Ruby core Exception documentation](https://rubyapi.org/3.0/o/exception)
10
12
 
11
13
  The core `Exception` class is enhanced to provide a better backtrace that takes
12
14
  into account the fiber hierarchy. In addition, a `source_fiber` attribute allows
13
15
  tracking the fiber from which an uncaught exception was propagated.
14
16
 
17
+
18
+
15
19
  ## Class Methods
16
20
 
17
21
  ## Instance methods
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ M = 100
7
+ N = 10000
8
+
9
+ GC.disable
10
+
11
+ def monotonic_clock
12
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
13
+ end
14
+
15
+ def spin_proc(next_fiber)
16
+ spin_loop { next_fiber << receive }
17
+ end
18
+
19
+ last = Fiber.current
20
+ N.times { last = spin_proc(last) }
21
+
22
+ snooze
23
+ t0 = monotonic_clock
24
+ M.times do
25
+ last << 'hello'
26
+ receive
27
+ end
28
+ elapsed = monotonic_clock - t0
29
+ puts "M=#{M} N=#{N} elapsed: #{elapsed}"
@@ -64,7 +64,8 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
64
64
  unsigned int idle_tasks_run_count = 0;
65
65
 
66
66
  base->switch_count++;
67
- COND_TRACE(base, 2, SYM_fiber_switchpoint, current_fiber);
67
+ if (SHOULD_TRACE(base))
68
+ TRACE(base, 3, SYM_fiber_switchpoint, current_fiber, CALLER());
68
69
 
69
70
  while (1) {
70
71
  next = runqueue_shift(&base->runqueue);
@@ -106,14 +107,14 @@ VALUE backend_base_switch_fiber(VALUE backend, struct Backend_base *base) {
106
107
 
107
108
  void backend_base_schedule_fiber(VALUE thread, VALUE backend, struct Backend_base *base, VALUE fiber, VALUE value, int prioritize) {
108
109
  int already_runnable;
110
+ runqueue_t *runqueue;
109
111
 
110
112
  if (rb_fiber_alive_p(fiber) != Qtrue) return;
111
113
  already_runnable = rb_ivar_get(fiber, ID_ivar_runnable) != Qnil;
112
114
 
113
115
  COND_TRACE(base, 4, SYM_fiber_schedule, fiber, value, prioritize ? Qtrue : Qfalse);
114
116
 
115
- runqueue_t *runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ?
116
- &base->parked_runqueue : &base->runqueue;
117
+ runqueue = rb_ivar_get(fiber, ID_ivar_parked) == Qtrue ? &base->parked_runqueue : &base->runqueue;
117
118
 
118
119
  (prioritize ? runqueue_unshift : runqueue_push)(runqueue, fiber, value, already_runnable);
119
120
  if (!already_runnable) {
@@ -202,11 +203,40 @@ inline rb_encoding* io_read_encoding(rb_io_t *fptr) {
202
203
  }
203
204
 
204
205
  inline VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
205
- OBJ_TAINT(str);
206
206
  rb_enc_associate(str, io_read_encoding(fptr));
207
207
  return str;
208
208
  }
209
209
 
210
+ static inline void free_io_buffer(rb_io_buffer_t *buf)
211
+ {
212
+ if (buf->ptr) {
213
+ ruby_xfree(buf->ptr);
214
+ buf->ptr = NULL;
215
+ }
216
+ }
217
+
218
+ static inline void clear_codeconv(rb_io_t *fptr) {
219
+ if (fptr->readconv) {
220
+ rb_econv_close(fptr->readconv);
221
+ fptr->readconv = NULL;
222
+ }
223
+ free_io_buffer(&fptr->cbuf);
224
+
225
+ if (fptr->writeconv) {
226
+ rb_econv_close(fptr->writeconv);
227
+ fptr->writeconv = NULL;
228
+ }
229
+ fptr->writeconv_initialized = 0;
230
+ }
231
+
232
+ void fptr_finalize(rb_io_t *fptr) {
233
+ fptr->fd = -1;
234
+ fptr->stdio_file = 0;
235
+ free_io_buffer(&fptr->rbuf);
236
+ free_io_buffer(&fptr->wbuf);
237
+ clear_codeconv(fptr);
238
+ }
239
+
210
240
  //////////////////////////////////////////////////////////////////////
211
241
  //////////////////////////////////////////////////////////////////////
212
242
 
@@ -239,13 +269,25 @@ inline void rectify_io_file_pos(rb_io_t *fptr) {
239
269
 
240
270
  inline double current_time() {
241
271
  struct timespec ts;
272
+ double t;
273
+ uint64_t ns;
274
+
242
275
  clock_gettime(CLOCK_MONOTONIC, &ts);
243
- long long ns = ts.tv_sec;
276
+ ns = ts.tv_sec;
244
277
  ns = ns * 1e9 + ts.tv_nsec;
245
- double t = ns;
278
+ t = ns;
246
279
  return t / 1e9;
247
280
  }
248
281
 
282
+ inline uint64_t current_time_ns() {
283
+ struct timespec ts;
284
+ uint64_t ns;
285
+
286
+ clock_gettime(CLOCK_MONOTONIC, &ts);
287
+ ns = ts.tv_sec;
288
+ return ns * 1e9 + ts.tv_nsec;
289
+ }
290
+
249
291
  inline VALUE backend_timeout_exception(VALUE exception) {
250
292
  if (rb_obj_is_kind_of(exception, rb_cArray) == Qtrue)
251
293
  return rb_funcall(rb_ary_entry(exception, 0), ID_new, 1, rb_ary_entry(exception, 1));
@@ -270,6 +312,9 @@ VALUE Backend_timeout_ensure_safe(VALUE arg) {
270
312
  static VALUE empty_string = Qnil;
271
313
 
272
314
  VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
315
+ VALUE joined;
316
+ VALUE result;
317
+
273
318
  switch (RARRAY_LEN(ary)) {
274
319
  case 0:
275
320
  return Qnil;
@@ -280,14 +325,16 @@ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
280
325
  empty_string = rb_str_new_literal("");
281
326
  rb_global_variable(&empty_string);
282
327
  }
283
- VALUE joined = rb_ary_join(ary, empty_string);
284
- VALUE result = Backend_send(self, io, joined, flags);
328
+ joined = rb_ary_join(ary, empty_string);
329
+ result = Backend_send(self, io, joined, flags);
285
330
  RB_GC_GUARD(joined);
286
331
  return result;
287
332
  }
288
333
  }
289
334
 
290
335
  inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
336
+ int flags;
337
+ int is_nonblocking;
291
338
  VALUE blocking_mode = rb_ivar_get(io, ID_ivar_blocking_mode);
292
339
  if (blocking == blocking_mode) return;
293
340
 
@@ -297,9 +344,9 @@ inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
297
344
  if (blocking != Qtrue)
298
345
  rb_w32_set_nonblock(fptr->fd);
299
346
  #elif defined(F_GETFL)
300
- int flags = fcntl(fptr->fd, F_GETFL);
347
+ flags = fcntl(fptr->fd, F_GETFL);
301
348
  if (flags == -1) return;
302
- int is_nonblocking = flags & O_NONBLOCK;
349
+ is_nonblocking = flags & O_NONBLOCK;
303
350
 
304
351
  if (blocking == Qtrue) {
305
352
  if (!is_nonblocking) return;
@@ -313,12 +360,14 @@ inline void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking) {
313
360
  }
314
361
 
315
362
  inline void backend_run_idle_tasks(struct Backend_base *base) {
363
+ double now;
364
+
316
365
  if (base->idle_proc != Qnil)
317
366
  rb_funcall(base->idle_proc, ID_call, 0);
318
367
 
319
368
  if (base->idle_gc_period == 0) return;
320
369
 
321
- double now = current_time();
370
+ now = current_time();
322
371
  if (now - base->idle_gc_last_time < base->idle_gc_period) return;
323
372
 
324
373
  base->idle_gc_last_time = now;
@@ -367,6 +416,13 @@ VALUE Backend_stats(VALUE self) {
367
416
  return stats;
368
417
  }
369
418
 
419
+ VALUE Backend_verify_blocking_mode(VALUE self, VALUE io, VALUE blocking) {
420
+ rb_io_t *fptr;
421
+ GetOpenFile(io, fptr);
422
+ io_verify_blocking_mode(fptr, io, blocking);
423
+ return self;
424
+ }
425
+
370
426
  void backend_setup_stats_symbols() {
371
427
  SYM_runqueue_size = ID2SYM(rb_intern("runqueue_size"));
372
428
  SYM_runqueue_length = ID2SYM(rb_intern("runqueue_length"));
@@ -383,4 +439,26 @@ void backend_setup_stats_symbols() {
383
439
  rb_global_variable(&SYM_switch_count);
384
440
  rb_global_variable(&SYM_poll_count);
385
441
  rb_global_variable(&SYM_pending_ops);
386
- }
442
+ }
443
+
444
+ int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr) {
445
+ VALUE port_string;
446
+ struct addrinfo hints;
447
+ struct addrinfo *addrinfo_result;
448
+ int ret;
449
+
450
+ memset(&hints, 0, sizeof(struct addrinfo));
451
+ hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
452
+ hints.ai_socktype = SOCK_STREAM;
453
+
454
+ port_string = rb_funcall(port, ID_to_s, 0);
455
+ ret = getaddrinfo(StringValueCStr(host), StringValueCStr(port_string), &hints, &addrinfo_result);
456
+ RB_GC_GUARD(port_string);
457
+ if (ret != 0) {
458
+ VALUE msg = rb_str_new2(gai_strerror(ret));
459
+ rb_funcall(rb_mKernel, ID_raise, 1, msg);
460
+ RB_GC_GUARD(msg);
461
+ }
462
+ *ai_addr = addrinfo_result->ai_addr;
463
+ return addrinfo_result->ai_addrlen;
464
+ }
@@ -1,6 +1,11 @@
1
1
  #ifndef BACKEND_COMMON_H
2
2
  #define BACKEND_COMMON_H
3
3
 
4
+ #include <sys/types.h>
5
+ #include <arpa/inet.h>
6
+ #include <netinet/in.h>
7
+ #include <netdb.h>
8
+
4
9
  #include "ruby.h"
5
10
  #include "ruby/io.h"
6
11
  #include "runqueue.h"
@@ -68,6 +73,7 @@ void io_shrink_read_string(VALUE str, long n);
68
73
  void io_set_read_length(VALUE str, long n, int shrinkable);
69
74
  rb_encoding* io_read_encoding(rb_io_t *fptr);
70
75
  VALUE io_enc_str(VALUE str, rb_io_t *fptr);
76
+ void fptr_finalize(rb_io_t *fptr);
71
77
 
72
78
  //////////////////////////////////////////////////////////////////////
73
79
  //////////////////////////////////////////////////////////////////////
@@ -82,7 +88,6 @@ VALUE backend_snooze();
82
88
  shrinkable = io_setstrbuf(&str, len); \
83
89
  buf = RSTRING_PTR(str); \
84
90
  total = 0; \
85
- OBJ_TAINT(str); \
86
91
  }
87
92
 
88
93
  #define READ_LOOP_YIELD_STR() { \
@@ -101,13 +106,16 @@ VALUE backend_snooze();
101
106
 
102
107
  void rectify_io_file_pos(rb_io_t *fptr);
103
108
  double current_time();
109
+ uint64_t current_time_ns();
104
110
  VALUE backend_timeout_exception(VALUE exception);
105
111
  VALUE Backend_timeout_ensure_safe(VALUE arg);
106
112
  VALUE Backend_timeout_ensure_safe(VALUE arg);
107
113
  VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
108
114
  VALUE Backend_stats(VALUE self);
115
+ VALUE Backend_verify_blocking_mode(VALUE self, VALUE io, VALUE blocking);
109
116
  void backend_run_idle_tasks(struct Backend_base *base);
110
117
  void io_verify_blocking_mode(rb_io_t *fptr, VALUE io, VALUE blocking);
111
118
  void backend_setup_stats_symbols();
119
+ int backend_getaddrinfo(VALUE host, VALUE port, struct sockaddr **ai_addr);
112
120
 
113
121
  #endif /* BACKEND_COMMON_H */