polyphony 0.51.0 → 0.52.0

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.
@@ -1,3 +1,41 @@
1
+ /*
2
+ # Libev-based blocking ops backend for Polyphony
3
+
4
+ ## Backend initialization
5
+
6
+ The backend is initialized by creating an event loop. For the main thread the
7
+ default event loop is used, but we since we don't need to handle any signals
8
+ (see the waitpid implementation below) we might as well use a non-default event
9
+ loop for the main thread at some time in the future.
10
+
11
+ In addition, we create an async watcher that is used for interrupting the #poll
12
+ method from another thread.
13
+
14
+ ## Blocking operations
15
+
16
+ I/O operations start by making sure the io has been set to non-blocking
17
+ operation (O_NONBLOCK). That way, if the syscall would block, we'd get an
18
+ EWOULDBLOCK or EAGAIN instead of blocking.
19
+
20
+ Once the OS has indicated that the operation would block, we start a watcher
21
+ (its type corresponding to the desired operation), and call ev_xxxx_start. in We
22
+ then call Thread_switch_fiber and switch to another fiber while waiting for the
23
+ watcher to be triggered.
24
+
25
+ ## Polling for events
26
+
27
+ Backend_poll is called either once the corresponding thread has no more work to
28
+ do (no runnable fibers) or periodically while the thread is scheduling fibers in
29
+ order to prevent event starvation.
30
+
31
+ ## Behaviour of waitpid
32
+
33
+ On Linux 5.3+, pidfd_open will be used, otherwise a libev child watcher will be
34
+ used. Note that if a child watcher is used, waitpid will only work from the main
35
+ thread.
36
+
37
+ */
38
+
1
39
  #ifdef POLYPHONY_BACKEND_LIBEV
2
40
 
3
41
  #include <netdb.h>
@@ -76,17 +114,27 @@ void break_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
76
114
  // of a *blocking* event loop (waking it up) in a thread-safe, signal-safe manner
77
115
  }
78
116
 
117
+ inline struct ev_loop *libev_new_loop() {
118
+ #ifdef POLYPHONY_USE_PIDFD_OPEN
119
+ return ev_loop_new(EVFLAG_NOSIGMASK);
120
+ #else
121
+ int is_main_thread = (rb_thread_current() == rb_thread_main());
122
+ return is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
123
+ #endif
124
+ }
125
+
79
126
  static VALUE Backend_initialize(VALUE self) {
80
127
  Backend_t *backend;
81
- VALUE thread = rb_thread_current();
82
- int is_main_thread = (thread == rb_thread_main());
83
-
128
+
84
129
  GetBackend(self, backend);
85
- backend->ev_loop = is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
130
+ backend->ev_loop = libev_new_loop();
86
131
 
132
+ // start async watcher used for breaking a poll op (from another thread)
87
133
  ev_async_init(&backend->break_async, break_async_callback);
88
134
  ev_async_start(backend->ev_loop, &backend->break_async);
89
- ev_unref(backend->ev_loop); // don't count the break_async watcher
135
+ // the break_async watcher is unreferenced, in order for Backend_poll to not
136
+ // block when no other watcher is active
137
+ ev_unref(backend->ev_loop);
90
138
 
91
139
  backend->currently_polling = 0;
92
140
  backend->pending_count = 0;
@@ -672,6 +720,55 @@ error:
672
720
  return RAISE_EXCEPTION(switchpoint_result);
673
721
  }
674
722
 
723
+ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
724
+ Backend_t *backend;
725
+ struct libev_io watcher;
726
+ rb_io_t *fptr;
727
+ VALUE switchpoint_result = Qnil;
728
+ VALUE underlying_io;
729
+ char *buf = StringValuePtr(str);
730
+ long len = RSTRING_LEN(str);
731
+ long left = len;
732
+ int flags_int = NUM2INT(flags);
733
+
734
+ underlying_io = rb_ivar_get(io, ID_ivar_io);
735
+ if (underlying_io != Qnil) io = underlying_io;
736
+ GetBackend(self, backend);
737
+ io = rb_io_get_write_io(io);
738
+ GetOpenFile(io, fptr);
739
+ io_set_nonblock(fptr, io);
740
+ watcher.fiber = Qnil;
741
+
742
+ while (left > 0) {
743
+ ssize_t n = send(fptr->fd, buf, left, flags_int);
744
+ if (n < 0) {
745
+ int e = errno;
746
+ if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
747
+
748
+ switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
749
+
750
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
751
+ }
752
+ else {
753
+ buf += n;
754
+ left -= n;
755
+ }
756
+ }
757
+
758
+ if (watcher.fiber == Qnil) {
759
+ switchpoint_result = backend_snooze();
760
+
761
+ if (TEST_EXCEPTION(switchpoint_result)) goto error;
762
+ }
763
+
764
+ RB_GC_GUARD(watcher.fiber);
765
+ RB_GC_GUARD(switchpoint_result);
766
+
767
+ return INT2NUM(len);
768
+ error:
769
+ return RAISE_EXCEPTION(switchpoint_result);
770
+ }
771
+
675
772
  VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
676
773
  Backend_t *backend;
677
774
  rb_io_t *fptr;
@@ -799,6 +896,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
799
896
  return result;
800
897
  }
801
898
 
899
+ #ifdef POLYPHONY_USE_PIDFD_OPEN
802
900
  VALUE Backend_waitpid(VALUE self, VALUE pid) {
803
901
  int pid_int = NUM2INT(pid);
804
902
  int fd = pidfd_open(pid_int, 0);
@@ -811,18 +909,53 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
811
909
  RAISE_IF_EXCEPTION(resume_value);
812
910
  RB_GC_GUARD(resume_value);
813
911
  }
912
+ else {
913
+ int e = errno;
914
+ rb_syserr_fail(e, strerror(e));
915
+ }
814
916
 
815
917
  int status = 0;
816
918
  pid_t ret = waitpid(pid_int, &status, WNOHANG);
817
919
  if (ret < 0) {
818
920
  int e = errno;
819
- if (e == ECHILD)
820
- ret = pid_int;
821
- else
822
- rb_syserr_fail(e, strerror(e));
921
+ rb_syserr_fail(e, strerror(e));
823
922
  }
824
923
  return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
825
924
  }
925
+ #else
926
+ struct libev_child {
927
+ struct ev_child child;
928
+ VALUE fiber;
929
+ };
930
+
931
+ void Backend_child_callback(EV_P_ ev_child *w, int revents) {
932
+ struct libev_child *watcher = (struct libev_child *)w;
933
+ int exit_status = WEXITSTATUS(w->rstatus);
934
+ VALUE status;
935
+
936
+ status = rb_ary_new_from_args(2, INT2NUM(w->rpid), INT2NUM(exit_status));
937
+ Fiber_make_runnable(watcher->fiber, status);
938
+ }
939
+
940
+ VALUE Backend_waitpid(VALUE self, VALUE pid) {
941
+ Backend_t *backend;
942
+ struct libev_child watcher;
943
+ VALUE switchpoint_result = Qnil;
944
+ GetBackend(self, backend);
945
+
946
+ watcher.fiber = rb_fiber_current();
947
+ ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
948
+ ev_child_start(backend->ev_loop, &watcher.child);
949
+
950
+ switchpoint_result = backend_await(backend);
951
+
952
+ ev_child_stop(backend->ev_loop, &watcher.child);
953
+ RAISE_IF_EXCEPTION(switchpoint_result);
954
+ RB_GC_GUARD(watcher.fiber);
955
+ RB_GC_GUARD(switchpoint_result);
956
+ return switchpoint_result;
957
+ }
958
+ #endif
826
959
 
827
960
  void Backend_async_callback(EV_P_ ev_async *w, int revents) { }
828
961
 
@@ -851,7 +984,7 @@ VALUE Backend_kind(VALUE self) {
851
984
  void Init_Backend() {
852
985
  ev_set_allocator(xrealloc);
853
986
 
854
- VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cData);
987
+ VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
855
988
  rb_define_alloc_func(cBackend, Backend_allocate);
856
989
 
857
990
  rb_define_method(cBackend, "initialize", Backend_initialize, 0);
@@ -871,7 +1004,8 @@ void Init_Backend() {
871
1004
  rb_define_method(cBackend, "recv", Backend_recv, 3);
872
1005
  rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
873
1006
  rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
874
- rb_define_method(cBackend, "send", Backend_write, 2);
1007
+ rb_define_method(cBackend, "send", Backend_send, 3);
1008
+ rb_define_method(cBackend, "sendv", Backend_sendv, 3);
875
1009
  rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
876
1010
  rb_define_method(cBackend, "sleep", Backend_sleep, 1);
877
1011
  rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
@@ -77,7 +77,7 @@ VALUE Event_await(VALUE self) {
77
77
  }
78
78
 
79
79
  void Init_Event() {
80
- cEvent = rb_define_class_under(mPolyphony, "Event", rb_cData);
80
+ cEvent = rb_define_class_under(mPolyphony, "Event", rb_cObject);
81
81
  rb_define_alloc_func(cEvent, Event_allocate);
82
82
 
83
83
  rb_define_method(cEvent, "initialize", Event_initialize, 0);
@@ -4,15 +4,19 @@ require 'rubygems'
4
4
  require 'mkmf'
5
5
 
6
6
  use_liburing = false
7
+ use_pidfd_open = false
7
8
  force_use_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
8
9
 
9
- if !force_use_libev && RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
10
+ if RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
10
11
  kernel_minor_version = $1.gsub('.', '').to_i
11
- use_liburing = kernel_minor_version >= 6
12
+ use_liburing = !force_use_libev && kernel_minor_version >= 6
13
+ use_pidfd_open = kernel_minor_version >= 3
12
14
  end
13
15
 
16
+ $defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if use_pidfd_open
14
17
  if use_liburing
15
18
  $defs << "-DPOLYPHONY_BACKEND_LIBURING"
19
+ $defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
16
20
  $CFLAGS << " -Wno-pointer-arith"
17
21
  else
18
22
  $defs << "-DPOLYPHONY_BACKEND_LIBEV"
@@ -23,6 +27,7 @@ else
23
27
  $defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
24
28
  $defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
25
29
  $defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
30
+
26
31
  $CFLAGS << " -Wno-comment"
27
32
  $CFLAGS << " -Wno-unused-result"
28
33
  $CFLAGS << " -Wno-dangling-else"
@@ -46,11 +46,105 @@ VALUE Polyphony_trace(VALUE self, VALUE enabled) {
46
46
  return Qnil;
47
47
  }
48
48
 
49
+ #define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
50
+
51
+ VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
52
+ return Backend_accept(BACKEND(), server_socket, socket_class);
53
+ }
54
+
55
+ VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
56
+ return Backend_accept_loop(BACKEND(), server_socket, socket_class);
57
+ }
58
+
59
+ VALUE Polyphony_backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port) {
60
+ return Backend_connect(BACKEND(), io, addr, port);
61
+ }
62
+
63
+ VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
64
+ return Backend_feed_loop(BACKEND(), io, receiver, method);
65
+ }
66
+
67
+ VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
68
+ return Backend_read(BACKEND(), io, str, length, to_eof);
69
+ }
70
+
71
+ VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
72
+ return Backend_read_loop(BACKEND(), io);
73
+ }
74
+
75
+ VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
76
+ return Backend_recv(BACKEND(), io, str, length);
77
+ }
78
+
79
+ VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
80
+ return Backend_recv_loop(BACKEND(), io);
81
+ }
82
+
83
+ VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
84
+ return Backend_recv_feed_loop(BACKEND(), io, receiver, method);
85
+ }
86
+
87
+ VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
88
+ return Backend_send(BACKEND(), io, msg, flags);
89
+ }
90
+
91
+ VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
92
+ return Backend_sendv(BACKEND(), io, ary, flags);
93
+ }
94
+
95
+ VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
96
+ return Backend_sleep(BACKEND(), duration);
97
+ }
98
+
99
+ VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
100
+ return Backend_timeout(argc, argv, BACKEND());
101
+ }
102
+
103
+ VALUE Polyphony_backend_timer_loop(VALUE self, VALUE interval) {
104
+ return Backend_timer_loop(BACKEND(), interval);
105
+ }
106
+
107
+ VALUE Polyphony_backend_wait_event(VALUE self, VALUE raise) {
108
+ return Backend_wait_event(BACKEND(), raise);
109
+ }
110
+
111
+ VALUE Polyphony_backend_wait_io(VALUE self, VALUE io, VALUE write) {
112
+ return Backend_wait_io(BACKEND(), io, write);
113
+ }
114
+
115
+ VALUE Polyphony_backend_waitpid(VALUE self, VALUE pid) {
116
+ return Backend_waitpid(BACKEND(), pid);
117
+ }
118
+
119
+ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
120
+ return Backend_write_m(argc, argv, BACKEND());
121
+ }
122
+
49
123
  void Init_Polyphony() {
50
124
  mPolyphony = rb_define_module("Polyphony");
51
125
 
52
126
  rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
53
127
 
128
+ // backend methods
129
+ rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
130
+ rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
131
+ rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
132
+ rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
133
+ rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 4);
134
+ rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
135
+ rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
136
+ rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
137
+ rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
138
+ rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
139
+ rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
140
+ rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
141
+ rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
142
+ rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
143
+ rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
144
+ rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
145
+ rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
146
+ rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
147
+
54
148
  rb_define_global_function("snooze", Polyphony_snooze, 0);
55
149
  rb_define_global_function("suspend", Polyphony_suspend, 0);
56
150
 
@@ -23,9 +23,9 @@
23
23
  #define COND_TRACE(...) if (__tracing_enabled__) { TRACE(__VA_ARGS__); }
24
24
 
25
25
  // exceptions
26
- #define TEST_EXCEPTION(ret) (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
26
+ #define TEST_EXCEPTION(ret) (rb_obj_is_kind_of(ret, rb_eException) == Qtrue)
27
27
  #define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
28
- #define RAISE_IF_EXCEPTION(ret) if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) { RAISE_EXCEPTION(ret); }
28
+ #define RAISE_IF_EXCEPTION(ret) if (rb_obj_is_kind_of(ret, rb_eException) == Qtrue) { RAISE_EXCEPTION(ret); }
29
29
  #define RAISE_IF_NOT_NIL(ret) if (ret != Qnil) { RAISE_EXCEPTION(ret); }
30
30
 
31
31
  // Fiber#transfer
@@ -89,6 +89,32 @@ void Runqueue_clear(VALUE self);
89
89
  long Runqueue_len(VALUE self);
90
90
  int Runqueue_empty_p(VALUE self);
91
91
 
92
+ #ifdef POLYPHONY_BACKEND_LIBEV
93
+ #define Backend_recv_loop Backend_read_loop
94
+ #define Backend_recv_feed_loop Backend_feed_loop
95
+ #endif
96
+
97
+ // Backend public interface
98
+
99
+ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
100
+ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
101
+ VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
102
+ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
103
+ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
104
+ VALUE Backend_read_loop(VALUE self, VALUE io);
105
+ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length);
106
+ VALUE Backend_recv_loop(VALUE self, VALUE io);
107
+ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
108
+ VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
109
+ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
110
+ VALUE Backend_sleep(VALUE self, VALUE duration);
111
+ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
112
+ VALUE Backend_timer_loop(VALUE self, VALUE interval);
113
+ VALUE Backend_wait_event(VALUE self, VALUE raise);
114
+ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
115
+ VALUE Backend_waitpid(VALUE self, VALUE pid);
116
+ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
117
+
92
118
  unsigned int Backend_pending_count(VALUE self);
93
119
  VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
94
120
  VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
@@ -247,7 +247,7 @@ VALUE Queue_size_m(VALUE self) {
247
247
  }
248
248
 
249
249
  void Init_Queue() {
250
- cQueue = rb_define_class_under(mPolyphony, "Queue", rb_cData);
250
+ cQueue = rb_define_class_under(mPolyphony, "Queue", rb_cObject);
251
251
  rb_define_alloc_func(cQueue, Queue_allocate);
252
252
 
253
253
  rb_define_method(cQueue, "initialize", Queue_initialize, -1);
@@ -101,7 +101,7 @@ int Runqueue_empty_p(VALUE self) {
101
101
  }
102
102
 
103
103
  void Init_Runqueue() {
104
- cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cData);
104
+ cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cObject);
105
105
  rb_define_alloc_func(cRunqueue, Runqueue_allocate);
106
106
 
107
107
  rb_define_method(cRunqueue, "initialize", Runqueue_initialize, 0);
@@ -16,7 +16,7 @@ if Object.constants.include?(:Reline)
16
16
  fiber.cancel
17
17
  end
18
18
  read_ios.each do |io|
19
- Thread.current.backend.wait_io(io, false)
19
+ Polyphony.backend_wait_io(io, false)
20
20
  return [io]
21
21
  end
22
22
  rescue Polyphony::Cancel
@@ -13,7 +13,7 @@ Mysql2::Client.prepend(Module.new do
13
13
 
14
14
  def query(sql, **options)
15
15
  super
16
- Thread.current.backend.wait_io(@io, false)
16
+ Polyphony.backend_wait_io(@io, false)
17
17
  async_result
18
18
  end
19
19
  end)
@@ -15,8 +15,8 @@ module ::PG
15
15
  res = conn.connect_poll
16
16
  case res
17
17
  when PGRES_POLLING_FAILED then raise Error, conn.error_message
18
- when PGRES_POLLING_READING then Thread.current.backend.wait_io(socket_io, false)
19
- when PGRES_POLLING_WRITING then Thread.current.backend.wait_io(socket_io, true)
18
+ when PGRES_POLLING_READING then Polyphony.backend_wait_io(socket_io, false)
19
+ when PGRES_POLLING_WRITING then Polyphony.backend_wait_io(socket_io, true)
20
20
  when PGRES_POLLING_OK then return conn.setnonblocking(true)
21
21
  end
22
22
  end
@@ -42,7 +42,7 @@ class ::PG::Connection
42
42
 
43
43
  def get_result(&block)
44
44
  while is_busy
45
- Thread.current.backend.wait_io(socket_io, false)
45
+ Polyphony.backend_wait_io(socket_io, false)
46
46
  consume_input
47
47
  end
48
48
  orig_get_result(&block)
@@ -59,7 +59,7 @@ class ::PG::Connection
59
59
 
60
60
  def block(_timeout = 0)
61
61
  while is_busy
62
- Thread.current.backend.wait_io(socket_io, false)
62
+ Polyphony.backend_wait_io(socket_io, false)
63
63
  consume_input
64
64
  end
65
65
  end
@@ -97,7 +97,7 @@ class ::PG::Connection
97
97
  return move_on_after(timeout) { wait_for_notify(&block) } if timeout
98
98
 
99
99
  while true
100
- Thread.current.backend.wait_io(socket_io, false)
100
+ Polyphony.backend_wait_io(socket_io, false)
101
101
  consume_input
102
102
  notice = notifies
103
103
  next unless notice