polyphony 0.53.1 → 0.57.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.gitignore +3 -1
- data/CHANGELOG.md +50 -24
- data/Gemfile.lock +3 -1
- data/TODO.md +0 -3
- data/examples/core/idle_gc.rb +21 -0
- data/examples/core/queue.rb +19 -0
- data/examples/io/https_server.rb +30 -0
- data/examples/io/pipe.rb +11 -0
- data/examples/io/splice_chunks.rb +29 -0
- data/examples/io/stdio.rb +8 -0
- data/ext/polyphony/backend_common.c +186 -0
- data/ext/polyphony/backend_common.h +25 -130
- data/ext/polyphony/backend_io_uring.c +369 -108
- data/ext/polyphony/backend_io_uring_context.c +14 -2
- data/ext/polyphony/backend_io_uring_context.h +11 -11
- data/ext/polyphony/backend_libev.c +406 -94
- data/ext/polyphony/polyphony.c +17 -15
- data/ext/polyphony/polyphony.h +3 -0
- data/ext/polyphony/runqueue.c +29 -1
- data/ext/polyphony/thread.c +19 -4
- data/lib/polyphony/core/sync.rb +8 -0
- data/lib/polyphony/extensions/openssl.rb +24 -17
- data/lib/polyphony/extensions/socket.rb +6 -20
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -0
- data/test/helper.rb +3 -3
- data/test/test_backend.rb +109 -3
- data/test/test_fiber.rb +0 -1
- data/test/test_io.rb +6 -3
- data/test/test_signal.rb +1 -1
- data/test/test_sync.rb +43 -0
- data/test/test_thread_pool.rb +1 -1
- data/test/test_timer.rb +16 -10
- metadata +23 -2
@@ -1,4 +1,5 @@
|
|
1
1
|
#include <stdlib.h>
|
2
|
+
#include <assert.h>
|
2
3
|
#include "ruby.h"
|
3
4
|
#include "polyphony.h"
|
4
5
|
#include "backend_io_uring_context.h"
|
@@ -15,6 +16,7 @@ const char *op_type_to_str(enum op_type type) {
|
|
15
16
|
case OP_POLL: return "POLL";
|
16
17
|
case OP_ACCEPT: return "ACCEPT";
|
17
18
|
case OP_CONNECT: return "CONNECT";
|
19
|
+
case OP_CHAIN: return "CHAIN";
|
18
20
|
default: return "";
|
19
21
|
};
|
20
22
|
}
|
@@ -35,6 +37,7 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
35
37
|
ctx = malloc(sizeof(op_context_t));
|
36
38
|
}
|
37
39
|
ctx->id = (++store->last_id);
|
40
|
+
// printf("acquire %d (%s)\n", ctx->id, op_type_to_str(type));
|
38
41
|
|
39
42
|
ctx->prev = NULL;
|
40
43
|
ctx->next = store->taken;
|
@@ -44,13 +47,21 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
44
47
|
ctx->type = type;
|
45
48
|
ctx->fiber = rb_fiber_current();
|
46
49
|
ctx->resume_value = Qnil;
|
47
|
-
ctx->
|
50
|
+
ctx->ref_count = 2;
|
48
51
|
ctx->result = 0;
|
49
52
|
|
50
53
|
return ctx;
|
51
54
|
}
|
52
55
|
|
53
|
-
|
56
|
+
// returns true if ctx was released
|
57
|
+
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);
|
59
|
+
|
60
|
+
assert(ctx->ref_count);
|
61
|
+
|
62
|
+
ctx->ref_count--;
|
63
|
+
if (ctx->ref_count) return 0;
|
64
|
+
|
54
65
|
if (ctx->next) ctx->next->prev = ctx->prev;
|
55
66
|
if (ctx->prev) ctx->prev->next = ctx->next;
|
56
67
|
if (store->taken == ctx) store->taken = ctx->next;
|
@@ -59,6 +70,7 @@ inline void context_store_release(op_context_store_t *store, op_context_t *ctx)
|
|
59
70
|
ctx->next = store->available;
|
60
71
|
if (ctx->next) ctx->next->prev = ctx;
|
61
72
|
store->available = ctx;
|
73
|
+
return 1;
|
62
74
|
}
|
63
75
|
|
64
76
|
void context_store_free(op_context_store_t *store) {
|
@@ -14,14 +14,15 @@ enum op_type {
|
|
14
14
|
OP_TIMEOUT,
|
15
15
|
OP_POLL,
|
16
16
|
OP_ACCEPT,
|
17
|
-
OP_CONNECT
|
17
|
+
OP_CONNECT,
|
18
|
+
OP_CHAIN
|
18
19
|
};
|
19
20
|
|
20
21
|
typedef struct op_context {
|
21
22
|
struct op_context *prev;
|
22
23
|
struct op_context *next;
|
23
24
|
enum op_type type: 16;
|
24
|
-
int
|
25
|
+
unsigned int ref_count : 16;
|
25
26
|
int id;
|
26
27
|
int result;
|
27
28
|
VALUE fiber;
|
@@ -38,17 +39,16 @@ const char *op_type_to_str(enum op_type type);
|
|
38
39
|
|
39
40
|
void context_store_initialize(op_context_store_t *store);
|
40
41
|
op_context_t *context_store_acquire(op_context_store_t *store, enum op_type type);
|
41
|
-
|
42
|
+
int context_store_release(op_context_store_t *store, op_context_t *ctx);
|
42
43
|
void context_store_free(op_context_store_t *store);
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
if (ctx->
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
} \
|
45
|
+
inline unsigned int OP_CONTEXT_RELEASE(op_context_store_t *store, op_context_t *ctx) {
|
46
|
+
int completed = !ctx->ref_count;
|
47
|
+
if (ctx->ref_count)
|
48
|
+
ctx->ref_count -= 1;
|
49
|
+
else
|
50
|
+
context_store_release(store, ctx);
|
51
|
+
return completed;
|
52
52
|
}
|
53
53
|
|
54
54
|
#endif /* BACKEND_IO_URING_CONTEXT_H */
|
@@ -42,7 +42,6 @@ thread.
|
|
42
42
|
#define _GNU_SOURCE 1
|
43
43
|
#endif
|
44
44
|
|
45
|
-
#include <fcntl.h>
|
46
45
|
#include <netdb.h>
|
47
46
|
#include <sys/socket.h>
|
48
47
|
#include <sys/uio.h>
|
@@ -52,45 +51,22 @@ thread.
|
|
52
51
|
#include <stdnoreturn.h>
|
53
52
|
#include <sys/types.h>
|
54
53
|
#include <sys/wait.h>
|
54
|
+
#include <fcntl.h>
|
55
55
|
|
56
56
|
#include "polyphony.h"
|
57
57
|
#include "../libev/ev.h"
|
58
58
|
#include "ruby/io.h"
|
59
59
|
|
60
|
+
#include "../libev/ev.h"
|
61
|
+
#include "backend_common.h"
|
62
|
+
|
60
63
|
VALUE SYM_libev;
|
61
64
|
VALUE SYM_send;
|
62
65
|
VALUE SYM_splice;
|
63
66
|
VALUE SYM_write;
|
64
67
|
|
65
|
-
ID ID_ivar_is_nonblocking;
|
66
|
-
|
67
|
-
// Since we need to ensure that fd's are non-blocking before every I/O
|
68
|
-
// operation, here we improve upon Ruby's rb_io_set_nonblock by caching the
|
69
|
-
// "nonblock" state in an instance variable. Calling rb_ivar_get on every read
|
70
|
-
// is still much cheaper than doing a fcntl syscall on every read! Preliminary
|
71
|
-
// benchmarks (with a "hello world" HTTP server) show throughput is improved
|
72
|
-
// by 10-13%.
|
73
|
-
inline void io_set_nonblock(rb_io_t *fptr, VALUE io) {
|
74
|
-
VALUE is_nonblocking = rb_ivar_get(io, ID_ivar_is_nonblocking);
|
75
|
-
if (is_nonblocking == Qtrue) return;
|
76
|
-
|
77
|
-
rb_ivar_set(io, ID_ivar_is_nonblocking, Qtrue);
|
78
|
-
|
79
|
-
#ifdef _WIN32
|
80
|
-
rb_w32_set_nonblock(fptr->fd);
|
81
|
-
#elif defined(F_GETFL)
|
82
|
-
int oflags = fcntl(fptr->fd, F_GETFL);
|
83
|
-
if ((oflags == -1) && (oflags & O_NONBLOCK)) return;
|
84
|
-
oflags |= O_NONBLOCK;
|
85
|
-
fcntl(fptr->fd, F_SETFL, oflags);
|
86
|
-
#endif
|
87
|
-
}
|
88
|
-
|
89
68
|
typedef struct Backend_t {
|
90
|
-
|
91
|
-
unsigned int currently_polling;
|
92
|
-
unsigned int pending_count;
|
93
|
-
unsigned int poll_no_wait_count;
|
69
|
+
struct Backend_base base;
|
94
70
|
|
95
71
|
// implementation-specific fields
|
96
72
|
struct ev_loop *ev_loop;
|
@@ -143,9 +119,10 @@ static VALUE Backend_initialize(VALUE self) {
|
|
143
119
|
// block when no other watcher is active
|
144
120
|
ev_unref(backend->ev_loop);
|
145
121
|
|
146
|
-
backend->currently_polling = 0;
|
147
|
-
backend->pending_count = 0;
|
148
|
-
backend->
|
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;
|
149
126
|
|
150
127
|
return Qnil;
|
151
128
|
}
|
@@ -176,32 +153,21 @@ VALUE Backend_post_fork(VALUE self) {
|
|
176
153
|
return self;
|
177
154
|
}
|
178
155
|
|
179
|
-
unsigned int Backend_pending_count(VALUE self) {
|
156
|
+
inline unsigned int Backend_pending_count(VALUE self) {
|
180
157
|
Backend_t *backend;
|
181
158
|
GetBackend(self, backend);
|
182
159
|
|
183
|
-
return backend->pending_count;
|
160
|
+
return backend->base.pending_count;
|
184
161
|
}
|
185
162
|
|
186
163
|
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue) {
|
187
|
-
int is_nowait = nowait == Qtrue;
|
188
164
|
Backend_t *backend;
|
189
165
|
GetBackend(self, backend);
|
190
166
|
|
191
|
-
if (is_nowait) {
|
192
|
-
backend->poll_no_wait_count++;
|
193
|
-
if (backend->poll_no_wait_count < 10) return self;
|
194
|
-
|
195
|
-
long runnable_count = Runqueue_len(runqueue);
|
196
|
-
if (backend->poll_no_wait_count < runnable_count) return self;
|
197
|
-
}
|
198
|
-
|
199
|
-
backend->poll_no_wait_count = 0;
|
200
|
-
|
201
167
|
COND_TRACE(2, SYM_fiber_event_poll_enter, current_fiber);
|
202
|
-
backend->currently_polling = 1;
|
203
|
-
ev_run(backend->ev_loop,
|
204
|
-
backend->currently_polling = 0;
|
168
|
+
backend->base.currently_polling = 1;
|
169
|
+
ev_run(backend->ev_loop, nowait == Qtrue ? EVRUN_NOWAIT : EVRUN_ONCE);
|
170
|
+
backend->base.currently_polling = 0;
|
205
171
|
COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
|
206
172
|
|
207
173
|
return self;
|
@@ -211,7 +177,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
211
177
|
Backend_t *backend;
|
212
178
|
GetBackend(self, backend);
|
213
179
|
|
214
|
-
if (backend->currently_polling) {
|
180
|
+
if (backend->base.currently_polling) {
|
215
181
|
// Since the loop will run until at least one event has occurred, we signal
|
216
182
|
// the selector's associated async watcher, which will cause the ev loop to
|
217
183
|
// return. In contrast to using `ev_break` to break out of the loop, which
|
@@ -224,10 +190,6 @@ VALUE Backend_wakeup(VALUE self) {
|
|
224
190
|
return Qnil;
|
225
191
|
}
|
226
192
|
|
227
|
-
#include "../libev/ev.h"
|
228
|
-
|
229
|
-
#include "backend_common.h"
|
230
|
-
|
231
193
|
struct libev_io {
|
232
194
|
struct ev_io io;
|
233
195
|
VALUE fiber;
|
@@ -248,7 +210,7 @@ VALUE libev_wait_fd_with_watcher(Backend_t *backend, int fd, struct libev_io *wa
|
|
248
210
|
}
|
249
211
|
ev_io_start(backend->ev_loop, &watcher->io);
|
250
212
|
|
251
|
-
switchpoint_result = backend_await(backend);
|
213
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
252
214
|
|
253
215
|
ev_io_stop(backend->ev_loop, &watcher->io);
|
254
216
|
RB_GC_GUARD(switchpoint_result);
|
@@ -284,7 +246,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
284
246
|
if (underlying_io != Qnil) io = underlying_io;
|
285
247
|
GetOpenFile(io, fptr);
|
286
248
|
rb_io_check_byte_readable(fptr);
|
287
|
-
|
249
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
288
250
|
rectify_io_file_pos(fptr);
|
289
251
|
watcher.fiber = Qnil;
|
290
252
|
OBJ_TAINT(str);
|
@@ -301,7 +263,6 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
301
263
|
}
|
302
264
|
else {
|
303
265
|
switchpoint_result = backend_snooze();
|
304
|
-
|
305
266
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
306
267
|
|
307
268
|
if (n == 0) break; // EOF
|
@@ -356,7 +317,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
356
317
|
if (underlying_io != Qnil) io = underlying_io;
|
357
318
|
GetOpenFile(io, fptr);
|
358
319
|
rb_io_check_byte_readable(fptr);
|
359
|
-
|
320
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
360
321
|
rectify_io_file_pos(fptr);
|
361
322
|
watcher.fiber = Qnil;
|
362
323
|
|
@@ -408,7 +369,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
408
369
|
if (underlying_io != Qnil) io = underlying_io;
|
409
370
|
GetOpenFile(io, fptr);
|
410
371
|
rb_io_check_byte_readable(fptr);
|
411
|
-
|
372
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
412
373
|
rectify_io_file_pos(fptr);
|
413
374
|
watcher.fiber = Qnil;
|
414
375
|
|
@@ -456,7 +417,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
456
417
|
GetBackend(self, backend);
|
457
418
|
io = rb_io_get_write_io(io);
|
458
419
|
GetOpenFile(io, fptr);
|
459
|
-
|
420
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
460
421
|
watcher.fiber = Qnil;
|
461
422
|
|
462
423
|
while (left > 0) {
|
@@ -506,7 +467,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
506
467
|
GetBackend(self, backend);
|
507
468
|
io = rb_io_get_write_io(io);
|
508
469
|
GetOpenFile(io, fptr);
|
509
|
-
|
470
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
510
471
|
watcher.fiber = Qnil;
|
511
472
|
|
512
473
|
iov = malloc(iov_count * sizeof(struct iovec));
|
@@ -587,7 +548,7 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
587
548
|
|
588
549
|
GetBackend(self, backend);
|
589
550
|
GetOpenFile(server_socket, fptr);
|
590
|
-
|
551
|
+
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
591
552
|
watcher.fiber = Qnil;
|
592
553
|
while (1) {
|
593
554
|
fd = accept(fptr->fd, &addr, &len);
|
@@ -615,7 +576,7 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
615
576
|
fp->fd = fd;
|
616
577
|
fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
|
617
578
|
rb_io_ascii8bit_binmode(socket);
|
618
|
-
|
579
|
+
io_verify_blocking_mode(fp, socket, Qfalse);
|
619
580
|
rb_io_synchronized(fp);
|
620
581
|
|
621
582
|
// if (rsock_do_not_reverse_lookup) {
|
@@ -644,7 +605,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
644
605
|
|
645
606
|
GetBackend(self, backend);
|
646
607
|
GetOpenFile(server_socket, fptr);
|
647
|
-
|
608
|
+
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
648
609
|
watcher.fiber = Qnil;
|
649
610
|
|
650
611
|
while (1) {
|
@@ -672,7 +633,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
672
633
|
fp->fd = fd;
|
673
634
|
fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
|
674
635
|
rb_io_ascii8bit_binmode(socket);
|
675
|
-
|
636
|
+
io_verify_blocking_mode(fp, socket, Qfalse);
|
676
637
|
rb_io_synchronized(fp);
|
677
638
|
|
678
639
|
rb_yield(socket);
|
@@ -700,7 +661,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
700
661
|
|
701
662
|
GetBackend(self, backend);
|
702
663
|
GetOpenFile(sock, fptr);
|
703
|
-
|
664
|
+
io_verify_blocking_mode(fptr, sock, Qfalse);
|
704
665
|
watcher.fiber = Qnil;
|
705
666
|
|
706
667
|
addr.sin_family = AF_INET;
|
@@ -743,7 +704,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
743
704
|
GetBackend(self, backend);
|
744
705
|
io = rb_io_get_write_io(io);
|
745
706
|
GetOpenFile(io, fptr);
|
746
|
-
|
707
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
747
708
|
watcher.fiber = Qnil;
|
748
709
|
|
749
710
|
while (left > 0) {
|
@@ -776,10 +737,63 @@ error:
|
|
776
737
|
return RAISE_EXCEPTION(switchpoint_result);
|
777
738
|
}
|
778
739
|
|
779
|
-
|
740
|
+
struct libev_rw_ctx {
|
741
|
+
int ref_count;
|
742
|
+
VALUE fiber;
|
743
|
+
};
|
744
|
+
|
745
|
+
struct libev_ref_count_io {
|
746
|
+
struct ev_io io;
|
747
|
+
struct libev_rw_ctx *ctx;
|
748
|
+
};
|
749
|
+
|
750
|
+
struct libev_rw_io {
|
751
|
+
struct libev_ref_count_io r;
|
752
|
+
struct libev_ref_count_io w;
|
753
|
+
struct libev_rw_ctx ctx;
|
754
|
+
};
|
755
|
+
|
756
|
+
void Backend_rw_io_callback(EV_P_ ev_io *w, int revents)
|
757
|
+
{
|
758
|
+
struct libev_ref_count_io *watcher = (struct libev_ref_count_io *)w;
|
759
|
+
int ref_count = watcher->ctx->ref_count--;
|
760
|
+
if (!ref_count)
|
761
|
+
Fiber_make_runnable(watcher->ctx->fiber, Qnil);
|
762
|
+
}
|
763
|
+
|
764
|
+
VALUE libev_wait_rw_fd_with_watcher(Backend_t *backend, int r_fd, int w_fd, struct libev_rw_io *watcher) {
|
765
|
+
VALUE switchpoint_result = Qnil;
|
766
|
+
|
767
|
+
if (watcher->ctx.fiber == Qnil) watcher->ctx.fiber = rb_fiber_current();
|
768
|
+
watcher->ctx.ref_count = 0;
|
769
|
+
if (r_fd != -1) {
|
770
|
+
ev_io_init(&watcher->r.io, Backend_rw_io_callback, r_fd, EV_READ);
|
771
|
+
ev_io_start(backend->ev_loop, &watcher->r.io);
|
772
|
+
watcher->r.ctx = &watcher->ctx;
|
773
|
+
watcher->ctx.ref_count++;
|
774
|
+
}
|
775
|
+
if (w_fd != -1) {
|
776
|
+
ev_io_init(&watcher->w.io, Backend_rw_io_callback, w_fd, EV_WRITE);
|
777
|
+
ev_io_start(backend->ev_loop, &watcher->w.io);
|
778
|
+
watcher->w.ctx = &watcher->ctx;
|
779
|
+
watcher->ctx.ref_count++;
|
780
|
+
}
|
781
|
+
|
782
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
783
|
+
|
784
|
+
if (r_fd != -1) ev_io_stop(backend->ev_loop, &watcher->r.io);
|
785
|
+
if (w_fd != -1) ev_io_stop(backend->ev_loop, &watcher->w.io);
|
786
|
+
RB_GC_GUARD(switchpoint_result);
|
787
|
+
return switchpoint_result;
|
788
|
+
}
|
789
|
+
|
790
|
+
|
791
|
+
|
792
|
+
|
793
|
+
#ifdef POLYPHONY_LINUX
|
780
794
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
781
795
|
Backend_t *backend;
|
782
|
-
struct
|
796
|
+
struct libev_rw_io watcher;
|
783
797
|
VALUE switchpoint_result = Qnil;
|
784
798
|
VALUE underlying_io;
|
785
799
|
rb_io_t *src_fptr;
|
@@ -791,25 +805,22 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
791
805
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
792
806
|
if (underlying_io != Qnil) src = underlying_io;
|
793
807
|
GetOpenFile(src, src_fptr);
|
794
|
-
|
808
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
795
809
|
|
796
810
|
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
797
811
|
if (underlying_io != Qnil) dest = underlying_io;
|
798
812
|
dest = rb_io_get_write_io(dest);
|
799
813
|
GetOpenFile(dest, dest_fptr);
|
800
|
-
|
814
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
801
815
|
|
802
|
-
watcher.fiber = Qnil;
|
816
|
+
watcher.ctx.fiber = Qnil;
|
803
817
|
while (1) {
|
804
818
|
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
805
819
|
if (len < 0) {
|
806
820
|
int e = errno;
|
807
821
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
808
822
|
|
809
|
-
switchpoint_result =
|
810
|
-
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
811
|
-
|
812
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
823
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fptr->fd, dest_fptr->fd, &watcher);
|
813
824
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
814
825
|
}
|
815
826
|
else {
|
@@ -817,12 +828,12 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
817
828
|
}
|
818
829
|
}
|
819
830
|
|
820
|
-
if (watcher.fiber == Qnil) {
|
831
|
+
if (watcher.ctx.fiber == Qnil) {
|
821
832
|
switchpoint_result = backend_snooze();
|
822
833
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
823
834
|
}
|
824
835
|
|
825
|
-
RB_GC_GUARD(watcher.fiber);
|
836
|
+
RB_GC_GUARD(watcher.ctx.fiber);
|
826
837
|
RB_GC_GUARD(switchpoint_result);
|
827
838
|
|
828
839
|
return INT2NUM(len);
|
@@ -832,7 +843,7 @@ error:
|
|
832
843
|
|
833
844
|
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
834
845
|
Backend_t *backend;
|
835
|
-
struct
|
846
|
+
struct libev_rw_io watcher;
|
836
847
|
VALUE switchpoint_result = Qnil;
|
837
848
|
VALUE underlying_io;
|
838
849
|
rb_io_t *src_fptr;
|
@@ -845,25 +856,22 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
845
856
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
846
857
|
if (underlying_io != Qnil) src = underlying_io;
|
847
858
|
GetOpenFile(src, src_fptr);
|
848
|
-
|
859
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
849
860
|
|
850
861
|
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
851
862
|
if (underlying_io != Qnil) dest = underlying_io;
|
852
863
|
dest = rb_io_get_write_io(dest);
|
853
864
|
GetOpenFile(dest, dest_fptr);
|
854
|
-
|
865
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
855
866
|
|
856
|
-
watcher.fiber = Qnil;
|
867
|
+
watcher.ctx.fiber = Qnil;
|
857
868
|
while (1) {
|
858
869
|
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
859
870
|
if (len < 0) {
|
860
871
|
int e = errno;
|
861
872
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
862
873
|
|
863
|
-
switchpoint_result =
|
864
|
-
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
865
|
-
|
866
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
874
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fptr->fd, dest_fptr->fd, &watcher);
|
867
875
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
868
876
|
}
|
869
877
|
else if (len == 0) {
|
@@ -874,6 +882,79 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
874
882
|
}
|
875
883
|
}
|
876
884
|
|
885
|
+
if (watcher.ctx.fiber == Qnil) {
|
886
|
+
switchpoint_result = backend_snooze();
|
887
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
888
|
+
}
|
889
|
+
|
890
|
+
RB_GC_GUARD(watcher.ctx.fiber);
|
891
|
+
RB_GC_GUARD(switchpoint_result);
|
892
|
+
|
893
|
+
return INT2NUM(total);
|
894
|
+
error:
|
895
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
896
|
+
}
|
897
|
+
#endif
|
898
|
+
|
899
|
+
VALUE Backend_fake_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
900
|
+
Backend_t *backend;
|
901
|
+
struct libev_io watcher;
|
902
|
+
VALUE switchpoint_result = Qnil;
|
903
|
+
VALUE underlying_io;
|
904
|
+
rb_io_t *src_fptr;
|
905
|
+
rb_io_t *dest_fptr;
|
906
|
+
int len = NUM2INT(maxlen);
|
907
|
+
VALUE str = rb_str_new(0, len);
|
908
|
+
char *buf = RSTRING_PTR(str);
|
909
|
+
int left = 0;
|
910
|
+
int total = 0;
|
911
|
+
|
912
|
+
GetBackend(self, backend);
|
913
|
+
|
914
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
915
|
+
if (underlying_io != Qnil) src = underlying_io;
|
916
|
+
GetOpenFile(src, src_fptr);
|
917
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
918
|
+
|
919
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
920
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
921
|
+
dest = rb_io_get_write_io(dest);
|
922
|
+
GetOpenFile(dest, dest_fptr);
|
923
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
924
|
+
|
925
|
+
watcher.fiber = Qnil;
|
926
|
+
|
927
|
+
while (1) {
|
928
|
+
ssize_t n = read(src_fptr->fd, buf, len);
|
929
|
+
if (n < 0) {
|
930
|
+
int e = errno;
|
931
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
932
|
+
|
933
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
934
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
935
|
+
}
|
936
|
+
else {
|
937
|
+
total = left = n;
|
938
|
+
break;
|
939
|
+
}
|
940
|
+
}
|
941
|
+
|
942
|
+
while (left > 0) {
|
943
|
+
ssize_t n = write(dest_fptr->fd, buf, left);
|
944
|
+
if (n < 0) {
|
945
|
+
int e = errno;
|
946
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
947
|
+
|
948
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
949
|
+
|
950
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
951
|
+
}
|
952
|
+
else {
|
953
|
+
buf += n;
|
954
|
+
left -= n;
|
955
|
+
}
|
956
|
+
}
|
957
|
+
|
877
958
|
if (watcher.fiber == Qnil) {
|
878
959
|
switchpoint_result = backend_snooze();
|
879
960
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
@@ -881,12 +962,90 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
881
962
|
|
882
963
|
RB_GC_GUARD(watcher.fiber);
|
883
964
|
RB_GC_GUARD(switchpoint_result);
|
965
|
+
RB_GC_GUARD(str);
|
966
|
+
|
967
|
+
return INT2NUM(total);
|
968
|
+
error:
|
969
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
970
|
+
}
|
971
|
+
|
972
|
+
VALUE Backend_fake_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
973
|
+
Backend_t *backend;
|
974
|
+
struct libev_io watcher;
|
975
|
+
VALUE switchpoint_result = Qnil;
|
976
|
+
VALUE underlying_io;
|
977
|
+
rb_io_t *src_fptr;
|
978
|
+
rb_io_t *dest_fptr;
|
979
|
+
int len = NUM2INT(maxlen);
|
980
|
+
VALUE str = rb_str_new(0, len);
|
981
|
+
char *buf = RSTRING_PTR(str);
|
982
|
+
int left = 0;
|
983
|
+
int total = 0;
|
984
|
+
|
985
|
+
GetBackend(self, backend);
|
986
|
+
|
987
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
988
|
+
if (underlying_io != Qnil) src = underlying_io;
|
989
|
+
GetOpenFile(src, src_fptr);
|
990
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
991
|
+
|
992
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
993
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
994
|
+
dest = rb_io_get_write_io(dest);
|
995
|
+
GetOpenFile(dest, dest_fptr);
|
996
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
997
|
+
|
998
|
+
watcher.fiber = Qnil;
|
999
|
+
|
1000
|
+
while (1) {
|
1001
|
+
char *ptr = buf;
|
1002
|
+
while (1) {
|
1003
|
+
ssize_t n = read(src_fptr->fd, ptr, len);
|
1004
|
+
if (n < 0) {
|
1005
|
+
int e = errno;
|
1006
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1007
|
+
|
1008
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
1009
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1010
|
+
}
|
1011
|
+
else if (n == 0) goto done;
|
1012
|
+
else {
|
1013
|
+
total += n;
|
1014
|
+
left = n;
|
1015
|
+
break;
|
1016
|
+
}
|
1017
|
+
}
|
1018
|
+
|
1019
|
+
while (left > 0) {
|
1020
|
+
ssize_t n = write(dest_fptr->fd, ptr, left);
|
1021
|
+
if (n < 0) {
|
1022
|
+
int e = errno;
|
1023
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1024
|
+
|
1025
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
1026
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1027
|
+
}
|
1028
|
+
else {
|
1029
|
+
ptr += n;
|
1030
|
+
left -= n;
|
1031
|
+
}
|
1032
|
+
}
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
done:
|
1036
|
+
if (watcher.fiber == Qnil) {
|
1037
|
+
switchpoint_result = backend_snooze();
|
1038
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
RB_GC_GUARD(watcher.fiber);
|
1042
|
+
RB_GC_GUARD(switchpoint_result);
|
1043
|
+
RB_GC_GUARD(str);
|
884
1044
|
|
885
1045
|
return INT2NUM(total);
|
886
1046
|
error:
|
887
1047
|
return RAISE_EXCEPTION(switchpoint_result);
|
888
1048
|
}
|
889
|
-
#endif
|
890
1049
|
|
891
1050
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
892
1051
|
Backend_t *backend;
|
@@ -921,7 +1080,7 @@ VALUE Backend_sleep(VALUE self, VALUE duration) {
|
|
921
1080
|
ev_timer_init(&watcher.timer, Backend_timer_callback, NUM2DBL(duration), 0.);
|
922
1081
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
923
1082
|
|
924
|
-
switchpoint_result = backend_await(backend);
|
1083
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
925
1084
|
|
926
1085
|
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
927
1086
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -949,7 +1108,7 @@ noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
949
1108
|
VALUE switchpoint_result = Qnil;
|
950
1109
|
ev_timer_init(&watcher.timer, Backend_timer_callback, sleep_duration, 0.);
|
951
1110
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
952
|
-
switchpoint_result = backend_await(backend);
|
1111
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
953
1112
|
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
954
1113
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
955
1114
|
RB_GC_GUARD(switchpoint_result);
|
@@ -1066,7 +1225,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1066
1225
|
ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
|
1067
1226
|
ev_child_start(backend->ev_loop, &watcher.child);
|
1068
1227
|
|
1069
|
-
switchpoint_result = backend_await(backend);
|
1228
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1070
1229
|
|
1071
1230
|
ev_child_stop(backend->ev_loop, &watcher.child);
|
1072
1231
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -1088,7 +1247,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1088
1247
|
ev_async_init(&async, Backend_async_callback);
|
1089
1248
|
ev_async_start(backend->ev_loop, &async);
|
1090
1249
|
|
1091
|
-
switchpoint_result = backend_await(backend);
|
1250
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1092
1251
|
|
1093
1252
|
ev_async_stop(backend->ev_loop, &async);
|
1094
1253
|
if (RTEST(raise)) RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -1113,10 +1272,8 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1113
1272
|
result = Backend_write(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
|
1114
1273
|
else if (op_type == SYM_send && op_len == 4)
|
1115
1274
|
result = Backend_send(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1116
|
-
#ifndef POLYPHONY_LINUX
|
1117
1275
|
else if (op_type == SYM_splice && op_len == 4)
|
1118
1276
|
result = Backend_splice(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1119
|
-
#endif
|
1120
1277
|
else
|
1121
1278
|
rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
|
1122
1279
|
}
|
@@ -1125,6 +1282,157 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1125
1282
|
return result;
|
1126
1283
|
}
|
1127
1284
|
|
1285
|
+
VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
|
1286
|
+
Backend_t *backend;
|
1287
|
+
GetBackend(self, backend);
|
1288
|
+
backend->base.idle_gc_period = NUM2DBL(period);
|
1289
|
+
backend->base.idle_gc_last_time = current_time();
|
1290
|
+
return self;
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
inline VALUE Backend_run_idle_tasks(VALUE self) {
|
1294
|
+
Backend_t *backend;
|
1295
|
+
GetBackend(self, backend);
|
1296
|
+
backend_run_idle_tasks(&backend->base);
|
1297
|
+
return self;
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
inline int splice_chunks_write(Backend_t *backend, int fd, VALUE str, struct libev_rw_io *watcher, VALUE *result) {
|
1301
|
+
char *buf = RSTRING_PTR(str);
|
1302
|
+
int len = RSTRING_LEN(str);
|
1303
|
+
int left = len;
|
1304
|
+
while (left > 0) {
|
1305
|
+
ssize_t n = write(fd, buf, left);
|
1306
|
+
if (n < 0) {
|
1307
|
+
int err = errno;
|
1308
|
+
if ((err != EWOULDBLOCK && err != EAGAIN)) return err;
|
1309
|
+
|
1310
|
+
*result = libev_wait_rw_fd_with_watcher(backend, -1, fd, watcher);
|
1311
|
+
if (TEST_EXCEPTION(*result)) return -1;
|
1312
|
+
}
|
1313
|
+
else {
|
1314
|
+
buf += n;
|
1315
|
+
left -= n;
|
1316
|
+
}
|
1317
|
+
}
|
1318
|
+
return 0;
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VALUE postfix, VALUE chunk_prefix, VALUE chunk_postfix, VALUE chunk_size) {
|
1322
|
+
Backend_t *backend;
|
1323
|
+
GetBackend(self, backend);
|
1324
|
+
int total = 0;
|
1325
|
+
int err = 0;
|
1326
|
+
VALUE result = Qnil;
|
1327
|
+
|
1328
|
+
rb_io_t *src_fptr;
|
1329
|
+
rb_io_t *dest_fptr;
|
1330
|
+
|
1331
|
+
VALUE underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1332
|
+
if (underlying_io != Qnil) src = underlying_io;
|
1333
|
+
GetOpenFile(src, src_fptr);
|
1334
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
1335
|
+
|
1336
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
1337
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
1338
|
+
dest = rb_io_get_write_io(dest);
|
1339
|
+
GetOpenFile(dest, dest_fptr);
|
1340
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
1341
|
+
|
1342
|
+
struct libev_rw_io watcher;
|
1343
|
+
watcher.ctx.fiber = Qnil;
|
1344
|
+
int maxlen = NUM2INT(chunk_size);
|
1345
|
+
VALUE str = Qnil;
|
1346
|
+
VALUE chunk_len_value = Qnil;
|
1347
|
+
|
1348
|
+
int pipefd[2] = { -1, -1 };
|
1349
|
+
if (pipe(pipefd) == -1) {
|
1350
|
+
err = errno;
|
1351
|
+
goto syscallerror;
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
|
1355
|
+
fcntl(pipefd[1], F_SETFL, O_NONBLOCK);
|
1356
|
+
|
1357
|
+
if (prefix != Qnil) {
|
1358
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, prefix, &watcher, &result);
|
1359
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1360
|
+
}
|
1361
|
+
while (1) {
|
1362
|
+
int chunk_len;
|
1363
|
+
// splice to pipe
|
1364
|
+
while (1) {
|
1365
|
+
chunk_len = splice(src_fptr->fd, 0, pipefd[1], 0, maxlen, 0);
|
1366
|
+
if (chunk_len < 0) {
|
1367
|
+
err = errno;
|
1368
|
+
if (err != EWOULDBLOCK && err != EAGAIN) goto syscallerror;
|
1369
|
+
|
1370
|
+
result = libev_wait_rw_fd_with_watcher(backend, src_fptr->fd, pipefd[1], &watcher);
|
1371
|
+
if (TEST_EXCEPTION(result)) goto error;
|
1372
|
+
}
|
1373
|
+
else {
|
1374
|
+
break;
|
1375
|
+
}
|
1376
|
+
}
|
1377
|
+
if (chunk_len == 0) break;
|
1378
|
+
|
1379
|
+
total += chunk_len;
|
1380
|
+
chunk_len_value = INT2NUM(chunk_len);
|
1381
|
+
|
1382
|
+
if (chunk_prefix != Qnil) {
|
1383
|
+
VALUE str = (TYPE(chunk_prefix) == T_STRING) ? chunk_prefix : rb_funcall(chunk_prefix, ID_call, 1, chunk_len_value);
|
1384
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, str, &watcher, &result);
|
1385
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1386
|
+
}
|
1387
|
+
|
1388
|
+
int left = chunk_len;
|
1389
|
+
while (1) {
|
1390
|
+
int n = splice(pipefd[0], 0, dest_fptr->fd, 0, left, 0);
|
1391
|
+
if (n < 0) {
|
1392
|
+
err = errno;
|
1393
|
+
if (err != EWOULDBLOCK && err != EAGAIN) goto syscallerror;
|
1394
|
+
|
1395
|
+
result = libev_wait_rw_fd_with_watcher(backend, pipefd[0], dest_fptr->fd, &watcher);
|
1396
|
+
if (TEST_EXCEPTION(result)) goto error;
|
1397
|
+
}
|
1398
|
+
else {
|
1399
|
+
left -= n;
|
1400
|
+
if (left == 0) break;
|
1401
|
+
}
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
if (chunk_postfix != Qnil) {
|
1405
|
+
VALUE str = (TYPE(chunk_postfix) == T_STRING) ? chunk_postfix : rb_funcall(chunk_postfix, ID_call, 1, chunk_len_value);
|
1406
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, str, &watcher, &result);
|
1407
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1408
|
+
}
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
if (postfix != Qnil) {
|
1412
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, postfix, &watcher, &result);
|
1413
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
if (watcher.ctx.fiber == Qnil) {
|
1417
|
+
result = backend_snooze();
|
1418
|
+
if (TEST_EXCEPTION(result)) goto error;
|
1419
|
+
}
|
1420
|
+
RB_GC_GUARD(str);
|
1421
|
+
RB_GC_GUARD(chunk_len_value);
|
1422
|
+
RB_GC_GUARD(result);
|
1423
|
+
if (pipefd[0] != -1) close(pipefd[0]);
|
1424
|
+
if (pipefd[1] != -1) close(pipefd[1]);
|
1425
|
+
return INT2NUM(total);
|
1426
|
+
syscallerror:
|
1427
|
+
if (pipefd[0] != -1) close(pipefd[0]);
|
1428
|
+
if (pipefd[1] != -1) close(pipefd[1]);
|
1429
|
+
rb_syserr_fail(err, strerror(err));
|
1430
|
+
error:
|
1431
|
+
if (pipefd[0] != -1) close(pipefd[0]);
|
1432
|
+
if (pipefd[1] != -1) close(pipefd[1]);
|
1433
|
+
return RAISE_EXCEPTION(result);
|
1434
|
+
}
|
1435
|
+
|
1128
1436
|
void Init_Backend() {
|
1129
1437
|
ev_set_allocator(xrealloc);
|
1130
1438
|
|
@@ -1139,6 +1447,8 @@ void Init_Backend() {
|
|
1139
1447
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1140
1448
|
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
1141
1449
|
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
1450
|
+
rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
|
1451
|
+
rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
|
1142
1452
|
|
1143
1453
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1144
1454
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
@@ -1153,9 +1463,12 @@ void Init_Backend() {
|
|
1153
1463
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
1154
1464
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
1155
1465
|
|
1156
|
-
#
|
1466
|
+
#ifdef POLYPHONY_LINUX
|
1157
1467
|
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1158
1468
|
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
1469
|
+
#else
|
1470
|
+
rb_define_method(cBackend, "splice", Backend_fake_splice, 3);
|
1471
|
+
rb_define_method(cBackend, "splice_to_eof", Backend_fake_splice_to_eof, 3);
|
1159
1472
|
#endif
|
1160
1473
|
|
1161
1474
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
@@ -1165,7 +1478,6 @@ void Init_Backend() {
|
|
1165
1478
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1166
1479
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1167
1480
|
|
1168
|
-
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
1169
1481
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
1170
1482
|
|
1171
1483
|
SYM_send = ID2SYM(rb_intern("send"));
|