polyphony 0.57.0 → 0.60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Gemfile.lock +15 -29
  4. data/examples/core/message_based_supervision.rb +51 -0
  5. data/ext/polyphony/backend_common.c +108 -3
  6. data/ext/polyphony/backend_common.h +23 -0
  7. data/ext/polyphony/backend_io_uring.c +117 -39
  8. data/ext/polyphony/backend_io_uring_context.c +11 -3
  9. data/ext/polyphony/backend_io_uring_context.h +5 -3
  10. data/ext/polyphony/backend_libev.c +92 -30
  11. data/ext/polyphony/extconf.rb +2 -2
  12. data/ext/polyphony/fiber.c +1 -34
  13. data/ext/polyphony/polyphony.c +12 -19
  14. data/ext/polyphony/polyphony.h +10 -20
  15. data/ext/polyphony/polyphony_ext.c +0 -4
  16. data/ext/polyphony/queue.c +12 -12
  17. data/ext/polyphony/runqueue.c +17 -85
  18. data/ext/polyphony/runqueue.h +27 -0
  19. data/ext/polyphony/thread.c +10 -99
  20. data/lib/polyphony/core/timer.rb +2 -2
  21. data/lib/polyphony/extensions/fiber.rb +102 -82
  22. data/lib/polyphony/extensions/io.rb +10 -9
  23. data/lib/polyphony/extensions/openssl.rb +14 -4
  24. data/lib/polyphony/extensions/socket.rb +15 -15
  25. data/lib/polyphony/extensions/thread.rb +8 -0
  26. data/lib/polyphony/version.rb +1 -1
  27. data/polyphony.gemspec +0 -7
  28. data/test/test_backend.rb +71 -5
  29. data/test/test_ext.rb +1 -1
  30. data/test/test_fiber.rb +106 -18
  31. data/test/test_global_api.rb +1 -1
  32. data/test/test_io.rb +29 -0
  33. data/test/test_supervise.rb +100 -100
  34. data/test/test_thread.rb +57 -11
  35. data/test/test_thread_pool.rb +1 -1
  36. data/test/test_trace.rb +28 -49
  37. metadata +4 -108
  38. data/ext/polyphony/tracing.c +0 -11
  39. data/lib/polyphony/adapters/trace.rb +0 -138
@@ -25,6 +25,8 @@ void context_store_initialize(op_context_store_t *store) {
25
25
  store->last_id = 0;
26
26
  store->available = NULL;
27
27
  store->taken = NULL;
28
+ store->available_count = 0;
29
+ store->taken_count = 0;
28
30
  }
29
31
 
30
32
  inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_type type) {
@@ -32,13 +34,12 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
32
34
  if (ctx) {
33
35
  if (ctx->next) ctx->next->prev = NULL;
34
36
  store->available = ctx->next;
37
+ store->available_count--;
35
38
  }
36
39
  else {
37
40
  ctx = malloc(sizeof(op_context_t));
38
41
  }
39
42
  ctx->id = (++store->last_id);
40
- // printf("acquire %d (%s)\n", ctx->id, op_type_to_str(type));
41
-
42
43
  ctx->prev = NULL;
43
44
  ctx->next = store->taken;
44
45
  if (store->taken) store->taken->prev = ctx;
@@ -50,18 +51,25 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
50
51
  ctx->ref_count = 2;
51
52
  ctx->result = 0;
52
53
 
54
+ store->taken_count++;
55
+
56
+ // printf("acquire %p %d (%s, ref_count: %d) taken: %d\n", ctx, ctx->id, op_type_to_str(type), ctx->ref_count, store->taken_count);
57
+
53
58
  return ctx;
54
59
  }
55
60
 
56
61
  // returns true if ctx was released
57
62
  inline int context_store_release(op_context_store_t *store, op_context_t *ctx) {
58
- // printf("release %d (%s, ref_count: %d)\n", ctx->id, op_type_to_str(ctx->type), ctx->ref_count);
63
+ // printf("release %p %d (%s, ref_count: %d)\n", ctx, ctx->id, op_type_to_str(ctx->type), ctx->ref_count);
59
64
 
60
65
  assert(ctx->ref_count);
61
66
 
62
67
  ctx->ref_count--;
63
68
  if (ctx->ref_count) return 0;
64
69
 
70
+ store->taken_count--;
71
+ store->available_count++;
72
+
65
73
  if (ctx->next) ctx->next->prev = ctx->prev;
66
74
  if (ctx->prev) ctx->prev->next = ctx->next;
67
75
  if (store->taken == ctx) store->taken = ctx->next;
@@ -22,7 +22,7 @@ typedef struct op_context {
22
22
  struct op_context *prev;
23
23
  struct op_context *next;
24
24
  enum op_type type: 16;
25
- unsigned int ref_count : 16;
25
+ unsigned int ref_count : 16;
26
26
  int id;
27
27
  int result;
28
28
  VALUE fiber;
@@ -31,8 +31,10 @@ typedef struct op_context {
31
31
 
32
32
  typedef struct op_context_store {
33
33
  int last_id;
34
- op_context_t *available;
35
- op_context_t *taken;
34
+ op_context_t *available;
35
+ op_context_t *taken;
36
+ int available_count;
37
+ int taken_count;
36
38
  } op_context_store_t;
37
39
 
38
40
  const char *op_type_to_str(enum op_type type);
@@ -73,13 +73,23 @@ typedef struct Backend_t {
73
73
  struct ev_async break_async;
74
74
  } Backend_t;
75
75
 
76
+ static void Backend_mark(void *ptr) {
77
+ Backend_t *backend = ptr;
78
+ backend_base_mark(&backend->base);
79
+ }
80
+
81
+ static void Backend_free(void *ptr) {
82
+ Backend_t *backend = ptr;
83
+ backend_base_finalize(&backend->base);
84
+ }
85
+
76
86
  static size_t Backend_size(const void *ptr) {
77
87
  return sizeof(Backend_t);
78
88
  }
79
89
 
80
90
  static const rb_data_type_t Backend_type = {
81
91
  "LibevBackend",
82
- {0, 0, Backend_size,},
92
+ {Backend_mark, Backend_free, Backend_size,},
83
93
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY
84
94
  };
85
95
 
@@ -110,6 +120,8 @@ static VALUE Backend_initialize(VALUE self) {
110
120
  Backend_t *backend;
111
121
 
112
122
  GetBackend(self, backend);
123
+
124
+ backend_base_initialize(&backend->base);
113
125
  backend->ev_loop = libev_new_loop();
114
126
 
115
127
  // start async watcher used for breaking a poll op (from another thread)
@@ -119,11 +131,6 @@ static VALUE Backend_initialize(VALUE self) {
119
131
  // block when no other watcher is active
120
132
  ev_unref(backend->ev_loop);
121
133
 
122
- backend->base.currently_polling = 0;
123
- backend->base.pending_count = 0;
124
- backend->base.idle_gc_period = 0;
125
- backend->base.idle_gc_last_time = 0;
126
-
127
134
  return Qnil;
128
135
  }
129
136
 
@@ -153,24 +160,38 @@ VALUE Backend_post_fork(VALUE self) {
153
160
  return self;
154
161
  }
155
162
 
156
- inline unsigned int Backend_pending_count(VALUE self) {
163
+ inline VALUE Backend_poll(VALUE self, VALUE blocking) {
157
164
  Backend_t *backend;
158
165
  GetBackend(self, backend);
159
166
 
160
- return backend->base.pending_count;
167
+ COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_enter, rb_fiber_current());
168
+ backend->base.currently_polling = 1;
169
+ ev_run(backend->ev_loop, blocking == Qtrue ? EVRUN_ONCE : EVRUN_NOWAIT);
170
+ backend->base.currently_polling = 0;
171
+ COND_TRACE(&backend->base, 2, SYM_fiber_event_poll_leave, rb_fiber_current());
172
+
173
+ return self;
161
174
  }
162
175
 
163
- VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue) {
176
+ inline void Backend_schedule_fiber(VALUE thread, VALUE self, VALUE fiber, VALUE value, int prioritize) {
164
177
  Backend_t *backend;
165
178
  GetBackend(self, backend);
166
179
 
167
- COND_TRACE(2, SYM_fiber_event_poll_enter, current_fiber);
168
- backend->base.currently_polling = 1;
169
- ev_run(backend->ev_loop, nowait == Qtrue ? EVRUN_NOWAIT : EVRUN_ONCE);
170
- backend->base.currently_polling = 0;
171
- COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
180
+ backend_base_schedule_fiber(thread, self, &backend->base, fiber, value, prioritize);
181
+ }
172
182
 
173
- return self;
183
+ inline void Backend_unschedule_fiber(VALUE self, VALUE fiber) {
184
+ Backend_t *backend;
185
+ GetBackend(self, backend);
186
+
187
+ runqueue_delete(&backend->base.runqueue, fiber);
188
+ }
189
+
190
+ inline VALUE Backend_switch_fiber(VALUE self) {
191
+ Backend_t *backend;
192
+ GetBackend(self, backend);
193
+
194
+ return backend_base_switch_fiber(self, &backend->base);
174
195
  }
175
196
 
176
197
  VALUE Backend_wakeup(VALUE self) {
@@ -190,6 +211,16 @@ VALUE Backend_wakeup(VALUE self) {
190
211
  return Qnil;
191
212
  }
192
213
 
214
+ inline struct backend_stats Backend_stats(VALUE self) {
215
+ Backend_t *backend;
216
+ GetBackend(self, backend);
217
+
218
+ return (struct backend_stats){
219
+ .scheduled_fibers = runqueue_len(&backend->base.runqueue),
220
+ .pending_ops = backend->base.pending_count
221
+ };
222
+ }
223
+
193
224
  struct libev_io {
194
225
  struct ev_io io;
195
226
  VALUE fiber;
@@ -229,14 +260,20 @@ VALUE libev_wait_fd(Backend_t *backend, int fd, int events, int raise_exception)
229
260
  return switchpoint_result;
230
261
  }
231
262
 
232
- VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
263
+ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
233
264
  Backend_t *backend;
234
265
  struct libev_io watcher;
235
266
  rb_io_t *fptr;
236
267
  long dynamic_len = length == Qnil;
237
268
  long len = dynamic_len ? 4096 : NUM2INT(length);
238
- int shrinkable = io_setstrbuf(&str, len);
239
- char *buf = RSTRING_PTR(str);
269
+ long buf_pos = NUM2INT(pos);
270
+ if (str != Qnil) {
271
+ int current_len = RSTRING_LEN(str);
272
+ if (buf_pos < 0 || buf_pos > current_len) buf_pos = current_len;
273
+ }
274
+ else buf_pos = 0;
275
+ int shrinkable = io_setstrbuf(&str, buf_pos + len);
276
+ char *buf = RSTRING_PTR(str) + buf_pos;
240
277
  long total = 0;
241
278
  VALUE switchpoint_result = Qnil;
242
279
  int read_to_eof = RTEST(to_eof);
@@ -272,9 +309,9 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
272
309
  if (total == len) {
273
310
  if (!dynamic_len) break;
274
311
 
275
- rb_str_resize(str, total);
312
+ rb_str_resize(str, buf_pos + total);
276
313
  rb_str_modify_expand(str, len);
277
- buf = RSTRING_PTR(str) + total;
314
+ buf = RSTRING_PTR(str) + buf_pos + total;
278
315
  shrinkable = 0;
279
316
  len += len;
280
317
  }
@@ -282,7 +319,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
282
319
  }
283
320
  }
284
321
 
285
- io_set_read_length(str, total, shrinkable);
322
+ io_set_read_length(str, buf_pos + total, shrinkable);
286
323
  io_enc_str(str, fptr);
287
324
 
288
325
  if (total == 0) return Qnil;
@@ -295,17 +332,17 @@ error:
295
332
  return RAISE_EXCEPTION(switchpoint_result);
296
333
  }
297
334
 
298
- VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
299
- return Backend_read(self, io, str, length, Qnil);
335
+ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
336
+ return Backend_read(self, io, str, length, Qnil, pos);
300
337
  }
301
338
 
302
- VALUE Backend_read_loop(VALUE self, VALUE io) {
339
+ VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
303
340
  Backend_t *backend;
304
341
  struct libev_io watcher;
305
342
  rb_io_t *fptr;
306
343
  VALUE str;
307
344
  long total;
308
- long len = 8192;
345
+ long len = NUM2INT(maxlen);
309
346
  int shrinkable;
310
347
  char *buf;
311
348
  VALUE switchpoint_result = Qnil;
@@ -1290,6 +1327,13 @@ VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
1290
1327
  return self;
1291
1328
  }
1292
1329
 
1330
+ VALUE Backend_idle_proc_set(VALUE self, VALUE block) {
1331
+ Backend_t *backend;
1332
+ GetBackend(self, backend);
1333
+ backend->base.idle_proc = block;
1334
+ return self;
1335
+ }
1336
+
1293
1337
  inline VALUE Backend_run_idle_tasks(VALUE self) {
1294
1338
  Backend_t *backend;
1295
1339
  GetBackend(self, backend);
@@ -1433,6 +1477,21 @@ error:
1433
1477
  return RAISE_EXCEPTION(result);
1434
1478
  }
1435
1479
 
1480
+ VALUE Backend_trace(int argc, VALUE *argv, VALUE self) {
1481
+ Backend_t *backend;
1482
+ GetBackend(self, backend);
1483
+ backend_trace(&backend->base, argc, argv);
1484
+ return self;
1485
+ }
1486
+
1487
+ VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
1488
+ Backend_t *backend;
1489
+ GetBackend(self, backend);
1490
+
1491
+ backend->base.trace_proc = block;
1492
+ return self;
1493
+ }
1494
+
1436
1495
  void Init_Backend() {
1437
1496
  ev_set_allocator(xrealloc);
1438
1497
 
@@ -1442,22 +1501,25 @@ void Init_Backend() {
1442
1501
  rb_define_method(cBackend, "initialize", Backend_initialize, 0);
1443
1502
  rb_define_method(cBackend, "finalize", Backend_finalize, 0);
1444
1503
  rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
1504
+ rb_define_method(cBackend, "trace", Backend_trace, -1);
1505
+ rb_define_method(cBackend, "trace_proc=", Backend_trace_proc_set, 1);
1445
1506
 
1446
- rb_define_method(cBackend, "poll", Backend_poll, 3);
1507
+ rb_define_method(cBackend, "poll", Backend_poll, 1);
1447
1508
  rb_define_method(cBackend, "break", Backend_wakeup, 0);
1448
1509
  rb_define_method(cBackend, "kind", Backend_kind, 0);
1449
1510
  rb_define_method(cBackend, "chain", Backend_chain, -1);
1450
1511
  rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
1512
+ rb_define_method(cBackend, "idle_proc=", Backend_idle_proc_set, 1);
1451
1513
  rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
1452
1514
 
1453
1515
  rb_define_method(cBackend, "accept", Backend_accept, 2);
1454
1516
  rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
1455
1517
  rb_define_method(cBackend, "connect", Backend_connect, 3);
1456
1518
  rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
1457
- rb_define_method(cBackend, "read", Backend_read, 4);
1458
- rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
1459
- rb_define_method(cBackend, "recv", Backend_recv, 3);
1460
- rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
1519
+ rb_define_method(cBackend, "read", Backend_read, 5);
1520
+ rb_define_method(cBackend, "read_loop", Backend_read_loop, 2);
1521
+ rb_define_method(cBackend, "recv", Backend_recv, 4);
1522
+ rb_define_method(cBackend, "recv_loop", Backend_read_loop, 2);
1461
1523
  rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
1462
1524
  rb_define_method(cBackend, "send", Backend_send, 3);
1463
1525
  rb_define_method(cBackend, "sendv", Backend_sendv, 3);
@@ -8,8 +8,8 @@ use_pidfd_open = false
8
8
  force_use_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
9
9
  linux = RUBY_PLATFORM =~ /linux/
10
10
 
11
- if linux && `uname -sr` =~ /Linux 5\.([\d+])/
12
- kernel_minor_version = $1.gsub('.', '').to_i
11
+ if linux && `uname -sr` =~ /Linux 5\.(\d+)/
12
+ kernel_minor_version = $1.to_i
13
13
  use_liburing = !force_use_libev && kernel_minor_version >= 6
14
14
  use_pidfd_open = kernel_minor_version >= 3
15
15
  end
@@ -1,6 +1,5 @@
1
1
  #include "polyphony.h"
2
2
 
3
- ID ID_fiber_trace;
4
3
  ID ID_ivar_auto_watcher;
5
4
  ID ID_ivar_mailbox;
6
5
  ID ID_ivar_result;
@@ -82,34 +81,6 @@ static VALUE Fiber_state(VALUE self) {
82
81
  return SYM_waiting;
83
82
  }
84
83
 
85
- VALUE Fiber_await(VALUE self) {
86
- VALUE result;
87
-
88
- // we compare with false, since a fiber that has not yet started will have
89
- // @running set to nil
90
- if (rb_ivar_get(self, ID_ivar_running) == Qfalse) {
91
- result = rb_ivar_get(self, ID_ivar_result);
92
- RAISE_IF_EXCEPTION(result);
93
- return result;
94
- }
95
-
96
- VALUE fiber = rb_fiber_current();
97
- VALUE waiting_fibers = rb_ivar_get(self, ID_ivar_waiting_fibers);
98
- if (waiting_fibers == Qnil) {
99
- waiting_fibers = rb_hash_new();
100
- rb_ivar_set(self, ID_ivar_waiting_fibers, waiting_fibers);
101
- }
102
- rb_hash_aset(waiting_fibers, fiber, Qtrue);
103
-
104
- VALUE backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
105
- result = Backend_wait_event(backend, Qnil);
106
-
107
- rb_hash_delete(waiting_fibers, fiber);
108
- RAISE_IF_EXCEPTION(result);
109
- RB_GC_GUARD(result);
110
- return result;
111
- }
112
-
113
84
  VALUE Fiber_send(VALUE self, VALUE value) {
114
85
  VALUE mailbox = rb_ivar_get(self, ID_ivar_mailbox);
115
86
  if (mailbox == Qnil) {
@@ -126,7 +97,7 @@ VALUE Fiber_receive(VALUE self) {
126
97
  mailbox = rb_funcall(cQueue, ID_new, 0);
127
98
  rb_ivar_set(self, ID_ivar_mailbox, mailbox);
128
99
  }
129
- return Queue_shift(mailbox);
100
+ return Queue_shift(mailbox);
130
101
  }
131
102
 
132
103
  VALUE Fiber_mailbox(VALUE self) {
@@ -151,9 +122,6 @@ void Init_Fiber() {
151
122
  rb_define_method(cFiber, "state", Fiber_state, 0);
152
123
  rb_define_method(cFiber, "auto_watcher", Fiber_auto_watcher, 0);
153
124
 
154
- rb_define_method(cFiber, "await", Fiber_await, 0);
155
- rb_define_method(cFiber, "join", Fiber_await, 0);
156
-
157
125
  rb_define_method(cFiber, "<<", Fiber_send, 1);
158
126
  rb_define_method(cFiber, "send", Fiber_send, 1);
159
127
  rb_define_method(cFiber, "receive", Fiber_receive, 0);
@@ -169,7 +137,6 @@ void Init_Fiber() {
169
137
  rb_global_variable(&SYM_runnable);
170
138
  rb_global_variable(&SYM_waiting);
171
139
 
172
- ID_fiber_trace = rb_intern("__fiber_trace__");
173
140
  ID_ivar_auto_watcher = rb_intern("@auto_watcher");
174
141
  ID_ivar_mailbox = rb_intern("@mailbox");
175
142
  ID_ivar_result = rb_intern("@result");
@@ -42,11 +42,6 @@ static VALUE Polyphony_suspend(VALUE self) {
42
42
  return ret;
43
43
  }
44
44
 
45
- VALUE Polyphony_trace(VALUE self, VALUE enabled) {
46
- __tracing_enabled__ = RTEST(enabled) ? 1 : 0;
47
- return Qnil;
48
- }
49
-
50
45
  VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
51
46
  return Backend_accept(BACKEND(), server_socket, socket_class);
52
47
  }
@@ -63,20 +58,20 @@ VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE me
63
58
  return Backend_feed_loop(BACKEND(), io, receiver, method);
64
59
  }
65
60
 
66
- VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
67
- return Backend_read(BACKEND(), io, str, length, to_eof);
61
+ VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
62
+ return Backend_read(BACKEND(), io, str, length, to_eof, pos);
68
63
  }
69
64
 
70
- VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
71
- return Backend_read_loop(BACKEND(), io);
65
+ VALUE Polyphony_backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
66
+ return Backend_read_loop(BACKEND(), io, maxlen);
72
67
  }
73
68
 
74
- VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
75
- return Backend_recv(BACKEND(), io, str, length);
69
+ VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
70
+ return Backend_recv(BACKEND(), io, str, length, pos);
76
71
  }
77
72
 
78
- VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
79
- return Backend_recv_loop(BACKEND(), io);
73
+ VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
74
+ return Backend_recv_loop(BACKEND(), io, maxlen);
80
75
  }
81
76
 
82
77
  VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
@@ -130,17 +125,15 @@ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
130
125
  void Init_Polyphony() {
131
126
  mPolyphony = rb_define_module("Polyphony");
132
127
 
133
- rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
134
-
135
128
  // backend methods
136
129
  rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
137
130
  rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
138
131
  rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
139
132
  rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
140
- rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 4);
141
- rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
142
- rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
143
- rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
133
+ rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
134
+ rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
135
+ rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
136
+ rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 2);
144
137
  rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
145
138
  rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
146
139
  rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);