polyphony 0.50.0 → 0.53.1

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/CHANGELOG.md +30 -0
  4. data/Gemfile.lock +7 -68
  5. data/TODO.md +37 -6
  6. data/examples/core/forking.rb +2 -2
  7. data/examples/io/echo_server.rb +1 -0
  8. data/examples/io/tcp_proxy.rb +2 -2
  9. data/ext/polyphony/backend_common.h +57 -7
  10. data/ext/polyphony/backend_io_uring.c +232 -49
  11. data/ext/polyphony/backend_io_uring_context.c +1 -0
  12. data/ext/polyphony/backend_io_uring_context.h +1 -0
  13. data/ext/polyphony/backend_libev.c +355 -34
  14. data/ext/polyphony/event.c +1 -1
  15. data/ext/polyphony/extconf.rb +9 -2
  16. data/ext/polyphony/polyphony.c +102 -0
  17. data/ext/polyphony/polyphony.h +32 -2
  18. data/ext/polyphony/polyphony_ext.c +3 -0
  19. data/ext/polyphony/queue.c +1 -1
  20. data/ext/polyphony/runqueue.c +1 -1
  21. data/ext/polyphony/socket_extensions.c +33 -0
  22. data/ext/polyphony/thread.c +8 -2
  23. data/lib/polyphony/adapters/irb.rb +1 -1
  24. data/lib/polyphony/adapters/mysql2.rb +1 -1
  25. data/lib/polyphony/adapters/postgres.rb +5 -5
  26. data/lib/polyphony/adapters/process.rb +4 -4
  27. data/lib/polyphony/core/global_api.rb +5 -5
  28. data/lib/polyphony/core/sync.rb +1 -1
  29. data/lib/polyphony/core/throttler.rb +1 -1
  30. data/lib/polyphony/core/timer.rb +2 -2
  31. data/lib/polyphony/extensions/core.rb +1 -1
  32. data/lib/polyphony/extensions/io.rb +21 -22
  33. data/lib/polyphony/extensions/openssl.rb +6 -6
  34. data/lib/polyphony/extensions/socket.rb +56 -47
  35. data/lib/polyphony/version.rb +1 -1
  36. data/polyphony.gemspec +6 -5
  37. data/test/helper.rb +1 -1
  38. data/test/stress.rb +2 -0
  39. data/test/test_backend.rb +152 -5
  40. data/test/test_global_api.rb +2 -2
  41. data/test/test_io.rb +84 -1
  42. data/test/test_kernel.rb +1 -1
  43. data/test/test_signal.rb +1 -1
  44. data/test/test_socket.rb +61 -0
  45. data/test/test_thread.rb +4 -0
  46. data/test/test_timer.rb +1 -1
  47. metadata +19 -60
@@ -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,18 +4,24 @@ 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
9
+ linux = RUBY_PLATFORM =~ /linux/
8
10
 
9
- if !force_use_libev && RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
11
+ if linux && `uname -sr` =~ /Linux 5\.([\d+])/
10
12
  kernel_minor_version = $1.gsub('.', '').to_i
11
- use_liburing = kernel_minor_version >= 6
13
+ use_liburing = !force_use_libev && kernel_minor_version >= 6
14
+ use_pidfd_open = kernel_minor_version >= 3
12
15
  end
13
16
 
17
+ $defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if use_pidfd_open
14
18
  if use_liburing
15
19
  $defs << "-DPOLYPHONY_BACKEND_LIBURING"
20
+ $defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
16
21
  $CFLAGS << " -Wno-pointer-arith"
17
22
  else
18
23
  $defs << "-DPOLYPHONY_BACKEND_LIBEV"
24
+ $defs << "-DPOLYPHONY_LINUX" if linux
19
25
  $defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
20
26
  $defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
21
27
  $defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
@@ -23,6 +29,7 @@ else
23
29
  $defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
24
30
  $defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
25
31
  $defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
32
+
26
33
  $CFLAGS << " -Wno-comment"
27
34
  $CFLAGS << " -Wno-unused-result"
28
35
  $CFLAGS << " -Wno-dangling-else"
@@ -46,11 +46,113 @@ VALUE Polyphony_trace(VALUE self, VALUE enabled) {
46
46
  return Qnil;
47
47
  }
48
48
 
49
+ VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
50
+ return Backend_accept(BACKEND(), server_socket, socket_class);
51
+ }
52
+
53
+ VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
54
+ return Backend_accept_loop(BACKEND(), server_socket, socket_class);
55
+ }
56
+
57
+ VALUE Polyphony_backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port) {
58
+ return Backend_connect(BACKEND(), io, addr, port);
59
+ }
60
+
61
+ VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
62
+ return Backend_feed_loop(BACKEND(), io, receiver, method);
63
+ }
64
+
65
+ VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
66
+ return Backend_read(BACKEND(), io, str, length, to_eof);
67
+ }
68
+
69
+ VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
70
+ return Backend_read_loop(BACKEND(), io);
71
+ }
72
+
73
+ VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
74
+ return Backend_recv(BACKEND(), io, str, length);
75
+ }
76
+
77
+ VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
78
+ return Backend_recv_loop(BACKEND(), io);
79
+ }
80
+
81
+ VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
82
+ return Backend_recv_feed_loop(BACKEND(), io, receiver, method);
83
+ }
84
+
85
+ VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
86
+ return Backend_send(BACKEND(), io, msg, flags);
87
+ }
88
+
89
+ VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
90
+ return Backend_sendv(BACKEND(), io, ary, flags);
91
+ }
92
+
93
+ VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
94
+ return Backend_sleep(BACKEND(), duration);
95
+ }
96
+
97
+ VALUE Polyphony_backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
98
+ return Backend_splice(BACKEND(), src, dest, maxlen);
99
+ }
100
+
101
+ VALUE Polyphony_backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize) {
102
+ return Backend_splice_to_eof(BACKEND(), src, dest, chunksize);
103
+ }
104
+
105
+ VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
106
+ return Backend_timeout(argc, argv, BACKEND());
107
+ }
108
+
109
+ VALUE Polyphony_backend_timer_loop(VALUE self, VALUE interval) {
110
+ return Backend_timer_loop(BACKEND(), interval);
111
+ }
112
+
113
+ VALUE Polyphony_backend_wait_event(VALUE self, VALUE raise) {
114
+ return Backend_wait_event(BACKEND(), raise);
115
+ }
116
+
117
+ VALUE Polyphony_backend_wait_io(VALUE self, VALUE io, VALUE write) {
118
+ return Backend_wait_io(BACKEND(), io, write);
119
+ }
120
+
121
+ VALUE Polyphony_backend_waitpid(VALUE self, VALUE pid) {
122
+ return Backend_waitpid(BACKEND(), pid);
123
+ }
124
+
125
+ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
126
+ return Backend_write_m(argc, argv, BACKEND());
127
+ }
128
+
49
129
  void Init_Polyphony() {
50
130
  mPolyphony = rb_define_module("Polyphony");
51
131
 
52
132
  rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
53
133
 
134
+ // backend methods
135
+ rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
136
+ rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
137
+ rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
138
+ rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
139
+ rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 4);
140
+ rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
141
+ rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
142
+ rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
143
+ rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
144
+ rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
145
+ rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
146
+ rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
147
+ rb_define_singleton_method(mPolyphony, "backend_splice", Polyphony_backend_splice, 3);
148
+ rb_define_singleton_method(mPolyphony, "backend_splice_to_eof", Polyphony_backend_splice_to_eof, 3);
149
+ rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
150
+ rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
151
+ rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
152
+ rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
153
+ rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
154
+ rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
155
+
54
156
  rb_define_global_function("snooze", Polyphony_snooze, 0);
55
157
  rb_define_global_function("suspend", Polyphony_suspend, 0);
56
158
 
@@ -23,14 +23,16 @@
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
32
32
  #define FIBER_TRANSFER(fiber, value) rb_funcall(fiber, ID_transfer, 1, value)
33
33
 
34
+ #define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
35
+
34
36
  extern VALUE mPolyphony;
35
37
  extern VALUE cQueue;
36
38
  extern VALUE cEvent;
@@ -89,6 +91,34 @@ void Runqueue_clear(VALUE self);
89
91
  long Runqueue_len(VALUE self);
90
92
  int Runqueue_empty_p(VALUE self);
91
93
 
94
+ #ifdef POLYPHONY_BACKEND_LIBEV
95
+ #define Backend_recv_loop Backend_read_loop
96
+ #define Backend_recv_feed_loop Backend_feed_loop
97
+ #endif
98
+
99
+ // Backend public interface
100
+
101
+ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
102
+ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
103
+ VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
104
+ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
105
+ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
106
+ VALUE Backend_read_loop(VALUE self, VALUE io);
107
+ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length);
108
+ VALUE Backend_recv_loop(VALUE self, VALUE io);
109
+ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
110
+ VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
111
+ VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
112
+ VALUE Backend_sleep(VALUE self, VALUE duration);
113
+ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
114
+ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize);
115
+ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
116
+ VALUE Backend_timer_loop(VALUE self, VALUE interval);
117
+ VALUE Backend_wait_event(VALUE self, VALUE raise);
118
+ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
119
+ VALUE Backend_waitpid(VALUE self, VALUE pid);
120
+ VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
121
+
92
122
  unsigned int Backend_pending_count(VALUE self);
93
123
  VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
94
124
  VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
@@ -6,6 +6,7 @@ void Init_Backend();
6
6
  void Init_Queue();
7
7
  void Init_Event();
8
8
  void Init_Runqueue();
9
+ void Init_SocketExtensions();
9
10
  void Init_Thread();
10
11
  void Init_Tracing();
11
12
 
@@ -24,6 +25,8 @@ void Init_polyphony_ext() {
24
25
  Init_Thread();
25
26
  Init_Tracing();
26
27
 
28
+ Init_SocketExtensions();
29
+
27
30
  #ifdef POLYPHONY_PLAYGROUND
28
31
  playground();
29
32
  #endif
@@ -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);
@@ -0,0 +1,33 @@
1
+ #include "polyphony.h"
2
+
3
+ VALUE Socket_send(VALUE self, VALUE msg, VALUE flags) {
4
+ return Backend_send(BACKEND(), self, msg, flags);
5
+ }
6
+
7
+ VALUE Socket_write(int argc, VALUE *argv, VALUE self) {
8
+ VALUE ary = rb_ary_new_from_values(argc, argv);
9
+ VALUE result = Backend_sendv(BACKEND(), self, ary, INT2NUM(0));
10
+ RB_GC_GUARD(ary);
11
+ return result;
12
+ }
13
+
14
+ VALUE Socket_double_chevron(VALUE self, VALUE msg) {
15
+ Backend_send(BACKEND(), self, msg, INT2NUM(0));
16
+ return self;
17
+ }
18
+
19
+ void Init_SocketExtensions() {
20
+ rb_require("socket");
21
+
22
+ VALUE cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
23
+ VALUE cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
24
+
25
+ rb_define_method(cSocket, "send", Socket_send, 2);
26
+ rb_define_method(cTCPSocket, "send", Socket_send, 2);
27
+
28
+ rb_define_method(cSocket, "write", Socket_write, -1);
29
+ rb_define_method(cTCPSocket, "write", Socket_write, -1);
30
+
31
+ rb_define_method(cSocket, "<<", Socket_double_chevron, 1);
32
+ rb_define_method(cTCPSocket, "<<", Socket_double_chevron, 1);
33
+ }
@@ -21,7 +21,7 @@ static VALUE SYM_scheduled_fibers;
21
21
  static VALUE SYM_pending_watchers;
22
22
 
23
23
  static VALUE Thread_fiber_scheduling_stats(VALUE self) {
24
- VALUE backend = rb_ivar_get(self,ID_ivar_backend);
24
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
25
25
  VALUE stats = rb_hash_new();
26
26
  VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
27
27
  long pending_count;
@@ -53,7 +53,7 @@ void schedule_fiber(VALUE self, VALUE fiber, VALUE value, int prioritize) {
53
53
  // event selector. Otherwise it's gonna be stuck waiting for an event to
54
54
  // happen, not knowing that it there's already a fiber ready to run in its
55
55
  // run queue.
56
- VALUE backend = rb_ivar_get(self,ID_ivar_backend);
56
+ VALUE backend = rb_ivar_get(self, ID_ivar_backend);
57
57
  Backend_wakeup(backend);
58
58
  }
59
59
  }
@@ -138,6 +138,10 @@ VALUE Thread_debug(VALUE self) {
138
138
  return self;
139
139
  }
140
140
 
141
+ VALUE Thread_class_backend(VALUE _self) {
142
+ return rb_ivar_get(rb_thread_current(), ID_ivar_backend);
143
+ }
144
+
141
145
  void Init_Thread() {
142
146
  rb_define_method(rb_cThread, "setup_fiber_scheduling", Thread_setup_fiber_scheduling, 0);
143
147
  rb_define_method(rb_cThread, "fiber_scheduling_stats", Thread_fiber_scheduling_stats, 0);
@@ -150,6 +154,8 @@ void Init_Thread() {
150
154
  rb_define_method(rb_cThread, "fiber_scheduling_index", Thread_fiber_scheduling_index, 1);
151
155
  rb_define_method(rb_cThread, "fiber_unschedule", Thread_fiber_unschedule, 1);
152
156
 
157
+ rb_define_singleton_method(rb_cThread, "backend", Thread_class_backend, 0);
158
+
153
159
  rb_define_method(rb_cThread, "debug!", Thread_debug, 0);
154
160
 
155
161
  ID_deactivate_all_watchers_post_fork = rb_intern("deactivate_all_watchers_post_fork");
@@ -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
@@ -7,7 +7,7 @@ module Polyphony
7
7
  def watch(cmd = nil, &block)
8
8
  terminated = nil
9
9
  pid = cmd ? Kernel.spawn(cmd) : Polyphony.fork(&block)
10
- Thread.current.backend.waitpid(pid)
10
+ Polyphony.backend_waitpid(pid)
11
11
  terminated = true
12
12
  ensure
13
13
  kill_process(pid) unless terminated || pid.nil?
@@ -23,9 +23,9 @@ module Polyphony
23
23
 
24
24
  def kill_and_await(sig, pid)
25
25
  ::Process.kill(sig, pid)
26
- Thread.current.backend.waitpid(pid)
27
- rescue Errno::ERSCH
28
- # ignore
26
+ Polyphony.backend_waitpid(pid)
27
+ rescue Errno::ESRCH
28
+ # process doesn't exist
29
29
  end
30
30
  end
31
31
  end
@@ -21,7 +21,7 @@ module Polyphony
21
21
  elsif block.arity > 0
22
22
  cancel_after_with_block(Fiber.current, interval, with_exception, &block)
23
23
  else
24
- Thread.current.backend.timeout(interval, with_exception, &block)
24
+ Polyphony.backend_timeout(interval, with_exception, &block)
25
25
  end
26
26
  end
27
27
 
@@ -82,7 +82,7 @@ module Polyphony
82
82
  end
83
83
 
84
84
  def every(interval, &block)
85
- Thread.current.backend.timer_loop(interval, &block)
85
+ Polyphony.backend_timer_loop(interval, &block)
86
86
  end
87
87
 
88
88
  def move_on_after(interval, with_value: nil, &block)
@@ -91,7 +91,7 @@ module Polyphony
91
91
  elsif block.arity > 0
92
92
  move_on_after_with_block(Fiber.current, interval, with_value, &block)
93
93
  else
94
- Thread.current.backend.timeout(interval, nil, with_value, &block)
94
+ Polyphony.backend_timeout(interval, nil, with_value, &block)
95
95
  end
96
96
  end
97
97
 
@@ -129,11 +129,11 @@ module Polyphony
129
129
  def sleep(duration = nil)
130
130
  return sleep_forever unless duration
131
131
 
132
- Thread.current.backend.sleep duration
132
+ Polyphony.backend_sleep duration
133
133
  end
134
134
 
135
135
  def sleep_forever
136
- Thread.current.backend.wait_event(true)
136
+ Polyphony.backend_wait_event(true)
137
137
  end
138
138
 
139
139
  def throttled_loop(rate = nil, **opts, &block)
@@ -46,7 +46,7 @@ module Polyphony
46
46
  def wait(mutex, _timeout = nil)
47
47
  mutex.conditional_release
48
48
  @queue << Fiber.current
49
- Thread.current.backend.wait_event(true)
49
+ Polyphony.backend_wait_event(true)
50
50
  mutex.conditional_reacquire
51
51
  end
52
52