polyphony 0.55.0 → 0.59.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +1 -1
- data/examples/core/idle_gc.rb +21 -0
- data/examples/io/pipe.rb +11 -0
- data/examples/io/splice_chunks.rb +29 -0
- data/ext/polyphony/backend_common.c +288 -0
- data/ext/polyphony/backend_common.h +49 -130
- data/ext/polyphony/backend_io_uring.c +263 -54
- data/ext/polyphony/backend_io_uring_context.c +2 -3
- data/ext/polyphony/backend_libev.c +466 -84
- data/ext/polyphony/fiber.c +0 -2
- data/ext/polyphony/polyphony.c +17 -22
- data/ext/polyphony/polyphony.h +8 -16
- data/ext/polyphony/polyphony_ext.c +0 -4
- data/ext/polyphony/runqueue.c +17 -82
- data/ext/polyphony/runqueue.h +27 -0
- data/ext/polyphony/thread.c +10 -94
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/fiber.rb +2 -2
- data/lib/polyphony/extensions/thread.rb +8 -0
- data/lib/polyphony/version.rb +1 -1
- data/test/test_backend.rb +91 -0
- data/test/test_thread.rb +57 -11
- data/test/test_timer.rb +7 -7
- data/test/test_trace.rb +27 -49
- metadata +7 -4
- data/ext/polyphony/tracing.c +0 -11
- data/lib/polyphony/adapters/trace.rb +0 -138
@@ -37,8 +37,7 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
37
37
|
ctx = malloc(sizeof(op_context_t));
|
38
38
|
}
|
39
39
|
ctx->id = (++store->last_id);
|
40
|
-
// printf("acquire %d (%s)\n", ctx->id, op_type_to_str(type));
|
41
|
-
|
40
|
+
// printf("acquire %p %d (%s)\n", ctx, ctx->id, op_type_to_str(type));
|
42
41
|
ctx->prev = NULL;
|
43
42
|
ctx->next = store->taken;
|
44
43
|
if (store->taken) store->taken->prev = ctx;
|
@@ -55,7 +54,7 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
55
54
|
|
56
55
|
// returns true if ctx was released
|
57
56
|
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);
|
57
|
+
// printf("release %p %d (%s, ref_count: %d)\n", ctx, ctx->id, op_type_to_str(ctx->type), ctx->ref_count);
|
59
58
|
|
60
59
|
assert(ctx->ref_count);
|
61
60
|
|
@@ -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,57 +51,45 @@ 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;
|
69
|
+
struct Backend_base base;
|
93
70
|
|
94
71
|
// implementation-specific fields
|
95
72
|
struct ev_loop *ev_loop;
|
96
73
|
struct ev_async break_async;
|
97
74
|
} Backend_t;
|
98
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
|
+
|
99
86
|
static size_t Backend_size(const void *ptr) {
|
100
87
|
return sizeof(Backend_t);
|
101
88
|
}
|
102
89
|
|
103
90
|
static const rb_data_type_t Backend_type = {
|
104
91
|
"LibevBackend",
|
105
|
-
{
|
92
|
+
{Backend_mark, Backend_free, Backend_size,},
|
106
93
|
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
107
94
|
};
|
108
95
|
|
@@ -133,6 +120,8 @@ static VALUE Backend_initialize(VALUE self) {
|
|
133
120
|
Backend_t *backend;
|
134
121
|
|
135
122
|
GetBackend(self, backend);
|
123
|
+
|
124
|
+
backend_base_initialize(&backend->base);
|
136
125
|
backend->ev_loop = libev_new_loop();
|
137
126
|
|
138
127
|
// start async watcher used for breaking a poll op (from another thread)
|
@@ -142,9 +131,6 @@ static VALUE Backend_initialize(VALUE self) {
|
|
142
131
|
// block when no other watcher is active
|
143
132
|
ev_unref(backend->ev_loop);
|
144
133
|
|
145
|
-
backend->currently_polling = 0;
|
146
|
-
backend->pending_count = 0;
|
147
|
-
|
148
134
|
return Qnil;
|
149
135
|
}
|
150
136
|
|
@@ -174,31 +160,45 @@ VALUE Backend_post_fork(VALUE self) {
|
|
174
160
|
return self;
|
175
161
|
}
|
176
162
|
|
177
|
-
|
163
|
+
inline VALUE Backend_poll(VALUE self, VALUE blocking) {
|
178
164
|
Backend_t *backend;
|
179
165
|
GetBackend(self, backend);
|
180
166
|
|
181
|
-
|
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;
|
182
174
|
}
|
183
175
|
|
184
|
-
|
176
|
+
inline void Backend_schedule_fiber(VALUE thread, VALUE self, VALUE fiber, VALUE value, int prioritize) {
|
185
177
|
Backend_t *backend;
|
186
178
|
GetBackend(self, backend);
|
187
179
|
|
188
|
-
|
189
|
-
|
190
|
-
ev_run(backend->ev_loop, nowait == Qtrue ? EVRUN_NOWAIT : EVRUN_ONCE);
|
191
|
-
backend->currently_polling = 0;
|
192
|
-
COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
|
180
|
+
backend_base_schedule_fiber(thread, self, &backend->base, fiber, value, prioritize);
|
181
|
+
}
|
193
182
|
|
194
|
-
|
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);
|
195
195
|
}
|
196
196
|
|
197
197
|
VALUE Backend_wakeup(VALUE self) {
|
198
198
|
Backend_t *backend;
|
199
199
|
GetBackend(self, backend);
|
200
200
|
|
201
|
-
if (backend->currently_polling) {
|
201
|
+
if (backend->base.currently_polling) {
|
202
202
|
// Since the loop will run until at least one event has occurred, we signal
|
203
203
|
// the selector's associated async watcher, which will cause the ev loop to
|
204
204
|
// return. In contrast to using `ev_break` to break out of the loop, which
|
@@ -211,9 +211,16 @@ VALUE Backend_wakeup(VALUE self) {
|
|
211
211
|
return Qnil;
|
212
212
|
}
|
213
213
|
|
214
|
-
|
214
|
+
inline struct backend_stats Backend_stats(VALUE self) {
|
215
|
+
Backend_t *backend;
|
216
|
+
GetBackend(self, backend);
|
215
217
|
|
216
|
-
|
218
|
+
return (struct backend_stats){
|
219
|
+
.scheduled_fibers = runqueue_len(&backend->base.runqueue),
|
220
|
+
.waiting_fibers = 0,
|
221
|
+
.pending_ops = backend->base.pending_count
|
222
|
+
};
|
223
|
+
}
|
217
224
|
|
218
225
|
struct libev_io {
|
219
226
|
struct ev_io io;
|
@@ -235,7 +242,7 @@ VALUE libev_wait_fd_with_watcher(Backend_t *backend, int fd, struct libev_io *wa
|
|
235
242
|
}
|
236
243
|
ev_io_start(backend->ev_loop, &watcher->io);
|
237
244
|
|
238
|
-
switchpoint_result = backend_await(backend);
|
245
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
239
246
|
|
240
247
|
ev_io_stop(backend->ev_loop, &watcher->io);
|
241
248
|
RB_GC_GUARD(switchpoint_result);
|
@@ -271,7 +278,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
271
278
|
if (underlying_io != Qnil) io = underlying_io;
|
272
279
|
GetOpenFile(io, fptr);
|
273
280
|
rb_io_check_byte_readable(fptr);
|
274
|
-
|
281
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
275
282
|
rectify_io_file_pos(fptr);
|
276
283
|
watcher.fiber = Qnil;
|
277
284
|
OBJ_TAINT(str);
|
@@ -288,7 +295,6 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
288
295
|
}
|
289
296
|
else {
|
290
297
|
switchpoint_result = backend_snooze();
|
291
|
-
|
292
298
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
293
299
|
|
294
300
|
if (n == 0) break; // EOF
|
@@ -343,7 +349,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
343
349
|
if (underlying_io != Qnil) io = underlying_io;
|
344
350
|
GetOpenFile(io, fptr);
|
345
351
|
rb_io_check_byte_readable(fptr);
|
346
|
-
|
352
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
347
353
|
rectify_io_file_pos(fptr);
|
348
354
|
watcher.fiber = Qnil;
|
349
355
|
|
@@ -395,7 +401,7 @@ VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
395
401
|
if (underlying_io != Qnil) io = underlying_io;
|
396
402
|
GetOpenFile(io, fptr);
|
397
403
|
rb_io_check_byte_readable(fptr);
|
398
|
-
|
404
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
399
405
|
rectify_io_file_pos(fptr);
|
400
406
|
watcher.fiber = Qnil;
|
401
407
|
|
@@ -443,7 +449,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
443
449
|
GetBackend(self, backend);
|
444
450
|
io = rb_io_get_write_io(io);
|
445
451
|
GetOpenFile(io, fptr);
|
446
|
-
|
452
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
447
453
|
watcher.fiber = Qnil;
|
448
454
|
|
449
455
|
while (left > 0) {
|
@@ -493,7 +499,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
493
499
|
GetBackend(self, backend);
|
494
500
|
io = rb_io_get_write_io(io);
|
495
501
|
GetOpenFile(io, fptr);
|
496
|
-
|
502
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
497
503
|
watcher.fiber = Qnil;
|
498
504
|
|
499
505
|
iov = malloc(iov_count * sizeof(struct iovec));
|
@@ -574,7 +580,7 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
574
580
|
|
575
581
|
GetBackend(self, backend);
|
576
582
|
GetOpenFile(server_socket, fptr);
|
577
|
-
|
583
|
+
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
578
584
|
watcher.fiber = Qnil;
|
579
585
|
while (1) {
|
580
586
|
fd = accept(fptr->fd, &addr, &len);
|
@@ -602,7 +608,7 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
602
608
|
fp->fd = fd;
|
603
609
|
fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
|
604
610
|
rb_io_ascii8bit_binmode(socket);
|
605
|
-
|
611
|
+
io_verify_blocking_mode(fp, socket, Qfalse);
|
606
612
|
rb_io_synchronized(fp);
|
607
613
|
|
608
614
|
// if (rsock_do_not_reverse_lookup) {
|
@@ -631,7 +637,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
631
637
|
|
632
638
|
GetBackend(self, backend);
|
633
639
|
GetOpenFile(server_socket, fptr);
|
634
|
-
|
640
|
+
io_verify_blocking_mode(fptr, server_socket, Qfalse);
|
635
641
|
watcher.fiber = Qnil;
|
636
642
|
|
637
643
|
while (1) {
|
@@ -659,7 +665,7 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
659
665
|
fp->fd = fd;
|
660
666
|
fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
|
661
667
|
rb_io_ascii8bit_binmode(socket);
|
662
|
-
|
668
|
+
io_verify_blocking_mode(fp, socket, Qfalse);
|
663
669
|
rb_io_synchronized(fp);
|
664
670
|
|
665
671
|
rb_yield(socket);
|
@@ -687,7 +693,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
687
693
|
|
688
694
|
GetBackend(self, backend);
|
689
695
|
GetOpenFile(sock, fptr);
|
690
|
-
|
696
|
+
io_verify_blocking_mode(fptr, sock, Qfalse);
|
691
697
|
watcher.fiber = Qnil;
|
692
698
|
|
693
699
|
addr.sin_family = AF_INET;
|
@@ -730,7 +736,7 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
|
730
736
|
GetBackend(self, backend);
|
731
737
|
io = rb_io_get_write_io(io);
|
732
738
|
GetOpenFile(io, fptr);
|
733
|
-
|
739
|
+
io_verify_blocking_mode(fptr, io, Qfalse);
|
734
740
|
watcher.fiber = Qnil;
|
735
741
|
|
736
742
|
while (left > 0) {
|
@@ -763,10 +769,63 @@ error:
|
|
763
769
|
return RAISE_EXCEPTION(switchpoint_result);
|
764
770
|
}
|
765
771
|
|
772
|
+
struct libev_rw_ctx {
|
773
|
+
int ref_count;
|
774
|
+
VALUE fiber;
|
775
|
+
};
|
776
|
+
|
777
|
+
struct libev_ref_count_io {
|
778
|
+
struct ev_io io;
|
779
|
+
struct libev_rw_ctx *ctx;
|
780
|
+
};
|
781
|
+
|
782
|
+
struct libev_rw_io {
|
783
|
+
struct libev_ref_count_io r;
|
784
|
+
struct libev_ref_count_io w;
|
785
|
+
struct libev_rw_ctx ctx;
|
786
|
+
};
|
787
|
+
|
788
|
+
void Backend_rw_io_callback(EV_P_ ev_io *w, int revents)
|
789
|
+
{
|
790
|
+
struct libev_ref_count_io *watcher = (struct libev_ref_count_io *)w;
|
791
|
+
int ref_count = watcher->ctx->ref_count--;
|
792
|
+
if (!ref_count)
|
793
|
+
Fiber_make_runnable(watcher->ctx->fiber, Qnil);
|
794
|
+
}
|
795
|
+
|
796
|
+
VALUE libev_wait_rw_fd_with_watcher(Backend_t *backend, int r_fd, int w_fd, struct libev_rw_io *watcher) {
|
797
|
+
VALUE switchpoint_result = Qnil;
|
798
|
+
|
799
|
+
if (watcher->ctx.fiber == Qnil) watcher->ctx.fiber = rb_fiber_current();
|
800
|
+
watcher->ctx.ref_count = 0;
|
801
|
+
if (r_fd != -1) {
|
802
|
+
ev_io_init(&watcher->r.io, Backend_rw_io_callback, r_fd, EV_READ);
|
803
|
+
ev_io_start(backend->ev_loop, &watcher->r.io);
|
804
|
+
watcher->r.ctx = &watcher->ctx;
|
805
|
+
watcher->ctx.ref_count++;
|
806
|
+
}
|
807
|
+
if (w_fd != -1) {
|
808
|
+
ev_io_init(&watcher->w.io, Backend_rw_io_callback, w_fd, EV_WRITE);
|
809
|
+
ev_io_start(backend->ev_loop, &watcher->w.io);
|
810
|
+
watcher->w.ctx = &watcher->ctx;
|
811
|
+
watcher->ctx.ref_count++;
|
812
|
+
}
|
813
|
+
|
814
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
815
|
+
|
816
|
+
if (r_fd != -1) ev_io_stop(backend->ev_loop, &watcher->r.io);
|
817
|
+
if (w_fd != -1) ev_io_stop(backend->ev_loop, &watcher->w.io);
|
818
|
+
RB_GC_GUARD(switchpoint_result);
|
819
|
+
return switchpoint_result;
|
820
|
+
}
|
821
|
+
|
822
|
+
|
823
|
+
|
824
|
+
|
766
825
|
#ifdef POLYPHONY_LINUX
|
767
826
|
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
768
827
|
Backend_t *backend;
|
769
|
-
struct
|
828
|
+
struct libev_rw_io watcher;
|
770
829
|
VALUE switchpoint_result = Qnil;
|
771
830
|
VALUE underlying_io;
|
772
831
|
rb_io_t *src_fptr;
|
@@ -778,25 +837,22 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
778
837
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
779
838
|
if (underlying_io != Qnil) src = underlying_io;
|
780
839
|
GetOpenFile(src, src_fptr);
|
781
|
-
|
840
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
782
841
|
|
783
842
|
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
784
843
|
if (underlying_io != Qnil) dest = underlying_io;
|
785
844
|
dest = rb_io_get_write_io(dest);
|
786
845
|
GetOpenFile(dest, dest_fptr);
|
787
|
-
|
846
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
788
847
|
|
789
|
-
watcher.fiber = Qnil;
|
848
|
+
watcher.ctx.fiber = Qnil;
|
790
849
|
while (1) {
|
791
850
|
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
792
851
|
if (len < 0) {
|
793
852
|
int e = errno;
|
794
853
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
795
854
|
|
796
|
-
switchpoint_result =
|
797
|
-
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
798
|
-
|
799
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
855
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fptr->fd, dest_fptr->fd, &watcher);
|
800
856
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
801
857
|
}
|
802
858
|
else {
|
@@ -804,12 +860,12 @@ VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
804
860
|
}
|
805
861
|
}
|
806
862
|
|
807
|
-
if (watcher.fiber == Qnil) {
|
863
|
+
if (watcher.ctx.fiber == Qnil) {
|
808
864
|
switchpoint_result = backend_snooze();
|
809
865
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
810
866
|
}
|
811
867
|
|
812
|
-
RB_GC_GUARD(watcher.fiber);
|
868
|
+
RB_GC_GUARD(watcher.ctx.fiber);
|
813
869
|
RB_GC_GUARD(switchpoint_result);
|
814
870
|
|
815
871
|
return INT2NUM(len);
|
@@ -819,7 +875,7 @@ error:
|
|
819
875
|
|
820
876
|
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
821
877
|
Backend_t *backend;
|
822
|
-
struct
|
878
|
+
struct libev_rw_io watcher;
|
823
879
|
VALUE switchpoint_result = Qnil;
|
824
880
|
VALUE underlying_io;
|
825
881
|
rb_io_t *src_fptr;
|
@@ -832,25 +888,22 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
832
888
|
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
833
889
|
if (underlying_io != Qnil) src = underlying_io;
|
834
890
|
GetOpenFile(src, src_fptr);
|
835
|
-
|
891
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
836
892
|
|
837
893
|
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
838
894
|
if (underlying_io != Qnil) dest = underlying_io;
|
839
895
|
dest = rb_io_get_write_io(dest);
|
840
896
|
GetOpenFile(dest, dest_fptr);
|
841
|
-
|
897
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
842
898
|
|
843
|
-
watcher.fiber = Qnil;
|
899
|
+
watcher.ctx.fiber = Qnil;
|
844
900
|
while (1) {
|
845
901
|
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
846
902
|
if (len < 0) {
|
847
903
|
int e = errno;
|
848
904
|
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
849
905
|
|
850
|
-
switchpoint_result =
|
851
|
-
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
852
|
-
|
853
|
-
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
906
|
+
switchpoint_result = libev_wait_rw_fd_with_watcher(backend, src_fptr->fd, dest_fptr->fd, &watcher);
|
854
907
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
855
908
|
}
|
856
909
|
else if (len == 0) {
|
@@ -861,6 +914,79 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
861
914
|
}
|
862
915
|
}
|
863
916
|
|
917
|
+
if (watcher.ctx.fiber == Qnil) {
|
918
|
+
switchpoint_result = backend_snooze();
|
919
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
920
|
+
}
|
921
|
+
|
922
|
+
RB_GC_GUARD(watcher.ctx.fiber);
|
923
|
+
RB_GC_GUARD(switchpoint_result);
|
924
|
+
|
925
|
+
return INT2NUM(total);
|
926
|
+
error:
|
927
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
928
|
+
}
|
929
|
+
#endif
|
930
|
+
|
931
|
+
VALUE Backend_fake_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
932
|
+
Backend_t *backend;
|
933
|
+
struct libev_io watcher;
|
934
|
+
VALUE switchpoint_result = Qnil;
|
935
|
+
VALUE underlying_io;
|
936
|
+
rb_io_t *src_fptr;
|
937
|
+
rb_io_t *dest_fptr;
|
938
|
+
int len = NUM2INT(maxlen);
|
939
|
+
VALUE str = rb_str_new(0, len);
|
940
|
+
char *buf = RSTRING_PTR(str);
|
941
|
+
int left = 0;
|
942
|
+
int total = 0;
|
943
|
+
|
944
|
+
GetBackend(self, backend);
|
945
|
+
|
946
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
947
|
+
if (underlying_io != Qnil) src = underlying_io;
|
948
|
+
GetOpenFile(src, src_fptr);
|
949
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
950
|
+
|
951
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
952
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
953
|
+
dest = rb_io_get_write_io(dest);
|
954
|
+
GetOpenFile(dest, dest_fptr);
|
955
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
956
|
+
|
957
|
+
watcher.fiber = Qnil;
|
958
|
+
|
959
|
+
while (1) {
|
960
|
+
ssize_t n = read(src_fptr->fd, buf, len);
|
961
|
+
if (n < 0) {
|
962
|
+
int e = errno;
|
963
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
964
|
+
|
965
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
966
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
967
|
+
}
|
968
|
+
else {
|
969
|
+
total = left = n;
|
970
|
+
break;
|
971
|
+
}
|
972
|
+
}
|
973
|
+
|
974
|
+
while (left > 0) {
|
975
|
+
ssize_t n = write(dest_fptr->fd, buf, left);
|
976
|
+
if (n < 0) {
|
977
|
+
int e = errno;
|
978
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
979
|
+
|
980
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
981
|
+
|
982
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
983
|
+
}
|
984
|
+
else {
|
985
|
+
buf += n;
|
986
|
+
left -= n;
|
987
|
+
}
|
988
|
+
}
|
989
|
+
|
864
990
|
if (watcher.fiber == Qnil) {
|
865
991
|
switchpoint_result = backend_snooze();
|
866
992
|
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
@@ -868,12 +994,90 @@ VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
|
868
994
|
|
869
995
|
RB_GC_GUARD(watcher.fiber);
|
870
996
|
RB_GC_GUARD(switchpoint_result);
|
997
|
+
RB_GC_GUARD(str);
|
998
|
+
|
999
|
+
return INT2NUM(total);
|
1000
|
+
error:
|
1001
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
VALUE Backend_fake_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
1005
|
+
Backend_t *backend;
|
1006
|
+
struct libev_io watcher;
|
1007
|
+
VALUE switchpoint_result = Qnil;
|
1008
|
+
VALUE underlying_io;
|
1009
|
+
rb_io_t *src_fptr;
|
1010
|
+
rb_io_t *dest_fptr;
|
1011
|
+
int len = NUM2INT(maxlen);
|
1012
|
+
VALUE str = rb_str_new(0, len);
|
1013
|
+
char *buf = RSTRING_PTR(str);
|
1014
|
+
int left = 0;
|
1015
|
+
int total = 0;
|
1016
|
+
|
1017
|
+
GetBackend(self, backend);
|
1018
|
+
|
1019
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1020
|
+
if (underlying_io != Qnil) src = underlying_io;
|
1021
|
+
GetOpenFile(src, src_fptr);
|
1022
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
1023
|
+
|
1024
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
1025
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
1026
|
+
dest = rb_io_get_write_io(dest);
|
1027
|
+
GetOpenFile(dest, dest_fptr);
|
1028
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
1029
|
+
|
1030
|
+
watcher.fiber = Qnil;
|
1031
|
+
|
1032
|
+
while (1) {
|
1033
|
+
char *ptr = buf;
|
1034
|
+
while (1) {
|
1035
|
+
ssize_t n = read(src_fptr->fd, ptr, len);
|
1036
|
+
if (n < 0) {
|
1037
|
+
int e = errno;
|
1038
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1039
|
+
|
1040
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
1041
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1042
|
+
}
|
1043
|
+
else if (n == 0) goto done;
|
1044
|
+
else {
|
1045
|
+
total += n;
|
1046
|
+
left = n;
|
1047
|
+
break;
|
1048
|
+
}
|
1049
|
+
}
|
1050
|
+
|
1051
|
+
while (left > 0) {
|
1052
|
+
ssize_t n = write(dest_fptr->fd, ptr, left);
|
1053
|
+
if (n < 0) {
|
1054
|
+
int e = errno;
|
1055
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
1056
|
+
|
1057
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
1058
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1059
|
+
}
|
1060
|
+
else {
|
1061
|
+
ptr += n;
|
1062
|
+
left -= n;
|
1063
|
+
}
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
done:
|
1068
|
+
if (watcher.fiber == Qnil) {
|
1069
|
+
switchpoint_result = backend_snooze();
|
1070
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
RB_GC_GUARD(watcher.fiber);
|
1074
|
+
RB_GC_GUARD(switchpoint_result);
|
1075
|
+
RB_GC_GUARD(str);
|
871
1076
|
|
872
1077
|
return INT2NUM(total);
|
873
1078
|
error:
|
874
1079
|
return RAISE_EXCEPTION(switchpoint_result);
|
875
1080
|
}
|
876
|
-
#endif
|
877
1081
|
|
878
1082
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
879
1083
|
Backend_t *backend;
|
@@ -908,7 +1112,7 @@ VALUE Backend_sleep(VALUE self, VALUE duration) {
|
|
908
1112
|
ev_timer_init(&watcher.timer, Backend_timer_callback, NUM2DBL(duration), 0.);
|
909
1113
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
910
1114
|
|
911
|
-
switchpoint_result = backend_await(backend);
|
1115
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
912
1116
|
|
913
1117
|
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
914
1118
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -936,7 +1140,7 @@ noreturn VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
936
1140
|
VALUE switchpoint_result = Qnil;
|
937
1141
|
ev_timer_init(&watcher.timer, Backend_timer_callback, sleep_duration, 0.);
|
938
1142
|
ev_timer_start(backend->ev_loop, &watcher.timer);
|
939
|
-
switchpoint_result = backend_await(backend);
|
1143
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
940
1144
|
ev_timer_stop(backend->ev_loop, &watcher.timer);
|
941
1145
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
942
1146
|
RB_GC_GUARD(switchpoint_result);
|
@@ -1053,7 +1257,7 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
1053
1257
|
ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
|
1054
1258
|
ev_child_start(backend->ev_loop, &watcher.child);
|
1055
1259
|
|
1056
|
-
switchpoint_result = backend_await(backend);
|
1260
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1057
1261
|
|
1058
1262
|
ev_child_stop(backend->ev_loop, &watcher.child);
|
1059
1263
|
RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -1075,7 +1279,7 @@ VALUE Backend_wait_event(VALUE self, VALUE raise) {
|
|
1075
1279
|
ev_async_init(&async, Backend_async_callback);
|
1076
1280
|
ev_async_start(backend->ev_loop, &async);
|
1077
1281
|
|
1078
|
-
switchpoint_result = backend_await(backend);
|
1282
|
+
switchpoint_result = backend_await((struct Backend_base *)backend);
|
1079
1283
|
|
1080
1284
|
ev_async_stop(backend->ev_loop, &async);
|
1081
1285
|
if (RTEST(raise)) RAISE_IF_EXCEPTION(switchpoint_result);
|
@@ -1100,10 +1304,8 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1100
1304
|
result = Backend_write(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
|
1101
1305
|
else if (op_type == SYM_send && op_len == 4)
|
1102
1306
|
result = Backend_send(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1103
|
-
#ifdef POLYPHONY_LINUX
|
1104
1307
|
else if (op_type == SYM_splice && op_len == 4)
|
1105
1308
|
result = Backend_splice(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1106
|
-
#endif
|
1107
1309
|
else
|
1108
1310
|
rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
|
1109
1311
|
}
|
@@ -1112,6 +1314,179 @@ VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
|
1112
1314
|
return result;
|
1113
1315
|
}
|
1114
1316
|
|
1317
|
+
VALUE Backend_idle_gc_period_set(VALUE self, VALUE period) {
|
1318
|
+
Backend_t *backend;
|
1319
|
+
GetBackend(self, backend);
|
1320
|
+
backend->base.idle_gc_period = NUM2DBL(period);
|
1321
|
+
backend->base.idle_gc_last_time = current_time();
|
1322
|
+
return self;
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
VALUE Backend_idle_proc_set(VALUE self, VALUE block) {
|
1326
|
+
Backend_t *backend;
|
1327
|
+
GetBackend(self, backend);
|
1328
|
+
backend->base.idle_proc = block;
|
1329
|
+
return self;
|
1330
|
+
}
|
1331
|
+
|
1332
|
+
inline VALUE Backend_run_idle_tasks(VALUE self) {
|
1333
|
+
Backend_t *backend;
|
1334
|
+
GetBackend(self, backend);
|
1335
|
+
backend_run_idle_tasks(&backend->base);
|
1336
|
+
return self;
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
inline int splice_chunks_write(Backend_t *backend, int fd, VALUE str, struct libev_rw_io *watcher, VALUE *result) {
|
1340
|
+
char *buf = RSTRING_PTR(str);
|
1341
|
+
int len = RSTRING_LEN(str);
|
1342
|
+
int left = len;
|
1343
|
+
while (left > 0) {
|
1344
|
+
ssize_t n = write(fd, buf, left);
|
1345
|
+
if (n < 0) {
|
1346
|
+
int err = errno;
|
1347
|
+
if ((err != EWOULDBLOCK && err != EAGAIN)) return err;
|
1348
|
+
|
1349
|
+
*result = libev_wait_rw_fd_with_watcher(backend, -1, fd, watcher);
|
1350
|
+
if (TEST_EXCEPTION(*result)) return -1;
|
1351
|
+
}
|
1352
|
+
else {
|
1353
|
+
buf += n;
|
1354
|
+
left -= n;
|
1355
|
+
}
|
1356
|
+
}
|
1357
|
+
return 0;
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
VALUE Backend_splice_chunks(VALUE self, VALUE src, VALUE dest, VALUE prefix, VALUE postfix, VALUE chunk_prefix, VALUE chunk_postfix, VALUE chunk_size) {
|
1361
|
+
Backend_t *backend;
|
1362
|
+
GetBackend(self, backend);
|
1363
|
+
int total = 0;
|
1364
|
+
int err = 0;
|
1365
|
+
VALUE result = Qnil;
|
1366
|
+
|
1367
|
+
rb_io_t *src_fptr;
|
1368
|
+
rb_io_t *dest_fptr;
|
1369
|
+
|
1370
|
+
VALUE underlying_io = rb_ivar_get(src, ID_ivar_io);
|
1371
|
+
if (underlying_io != Qnil) src = underlying_io;
|
1372
|
+
GetOpenFile(src, src_fptr);
|
1373
|
+
io_verify_blocking_mode(src_fptr, src, Qfalse);
|
1374
|
+
|
1375
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
1376
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
1377
|
+
dest = rb_io_get_write_io(dest);
|
1378
|
+
GetOpenFile(dest, dest_fptr);
|
1379
|
+
io_verify_blocking_mode(dest_fptr, dest, Qfalse);
|
1380
|
+
|
1381
|
+
struct libev_rw_io watcher;
|
1382
|
+
watcher.ctx.fiber = Qnil;
|
1383
|
+
int maxlen = NUM2INT(chunk_size);
|
1384
|
+
VALUE str = Qnil;
|
1385
|
+
VALUE chunk_len_value = Qnil;
|
1386
|
+
|
1387
|
+
int pipefd[2] = { -1, -1 };
|
1388
|
+
if (pipe(pipefd) == -1) {
|
1389
|
+
err = errno;
|
1390
|
+
goto syscallerror;
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
|
1394
|
+
fcntl(pipefd[1], F_SETFL, O_NONBLOCK);
|
1395
|
+
|
1396
|
+
if (prefix != Qnil) {
|
1397
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, prefix, &watcher, &result);
|
1398
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1399
|
+
}
|
1400
|
+
while (1) {
|
1401
|
+
int chunk_len;
|
1402
|
+
// splice to pipe
|
1403
|
+
while (1) {
|
1404
|
+
chunk_len = splice(src_fptr->fd, 0, pipefd[1], 0, maxlen, 0);
|
1405
|
+
if (chunk_len < 0) {
|
1406
|
+
err = errno;
|
1407
|
+
if (err != EWOULDBLOCK && err != EAGAIN) goto syscallerror;
|
1408
|
+
|
1409
|
+
result = libev_wait_rw_fd_with_watcher(backend, src_fptr->fd, pipefd[1], &watcher);
|
1410
|
+
if (TEST_EXCEPTION(result)) goto error;
|
1411
|
+
}
|
1412
|
+
else {
|
1413
|
+
break;
|
1414
|
+
}
|
1415
|
+
}
|
1416
|
+
if (chunk_len == 0) break;
|
1417
|
+
|
1418
|
+
total += chunk_len;
|
1419
|
+
chunk_len_value = INT2NUM(chunk_len);
|
1420
|
+
|
1421
|
+
if (chunk_prefix != Qnil) {
|
1422
|
+
VALUE str = (TYPE(chunk_prefix) == T_STRING) ? chunk_prefix : rb_funcall(chunk_prefix, ID_call, 1, chunk_len_value);
|
1423
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, str, &watcher, &result);
|
1424
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1425
|
+
}
|
1426
|
+
|
1427
|
+
int left = chunk_len;
|
1428
|
+
while (1) {
|
1429
|
+
int n = splice(pipefd[0], 0, dest_fptr->fd, 0, left, 0);
|
1430
|
+
if (n < 0) {
|
1431
|
+
err = errno;
|
1432
|
+
if (err != EWOULDBLOCK && err != EAGAIN) goto syscallerror;
|
1433
|
+
|
1434
|
+
result = libev_wait_rw_fd_with_watcher(backend, pipefd[0], dest_fptr->fd, &watcher);
|
1435
|
+
if (TEST_EXCEPTION(result)) goto error;
|
1436
|
+
}
|
1437
|
+
else {
|
1438
|
+
left -= n;
|
1439
|
+
if (left == 0) break;
|
1440
|
+
}
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
if (chunk_postfix != Qnil) {
|
1444
|
+
VALUE str = (TYPE(chunk_postfix) == T_STRING) ? chunk_postfix : rb_funcall(chunk_postfix, ID_call, 1, chunk_len_value);
|
1445
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, str, &watcher, &result);
|
1446
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1447
|
+
}
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
if (postfix != Qnil) {
|
1451
|
+
int err = splice_chunks_write(backend, dest_fptr->fd, postfix, &watcher, &result);
|
1452
|
+
if (err == -1) goto error; else if (err) goto syscallerror;
|
1453
|
+
}
|
1454
|
+
|
1455
|
+
if (watcher.ctx.fiber == Qnil) {
|
1456
|
+
result = backend_snooze();
|
1457
|
+
if (TEST_EXCEPTION(result)) goto error;
|
1458
|
+
}
|
1459
|
+
RB_GC_GUARD(str);
|
1460
|
+
RB_GC_GUARD(chunk_len_value);
|
1461
|
+
RB_GC_GUARD(result);
|
1462
|
+
if (pipefd[0] != -1) close(pipefd[0]);
|
1463
|
+
if (pipefd[1] != -1) close(pipefd[1]);
|
1464
|
+
return INT2NUM(total);
|
1465
|
+
syscallerror:
|
1466
|
+
if (pipefd[0] != -1) close(pipefd[0]);
|
1467
|
+
if (pipefd[1] != -1) close(pipefd[1]);
|
1468
|
+
rb_syserr_fail(err, strerror(err));
|
1469
|
+
error:
|
1470
|
+
if (pipefd[0] != -1) close(pipefd[0]);
|
1471
|
+
if (pipefd[1] != -1) close(pipefd[1]);
|
1472
|
+
return RAISE_EXCEPTION(result);
|
1473
|
+
}
|
1474
|
+
|
1475
|
+
VALUE Backend_trace(int argc, VALUE *argv, VALUE self) {
|
1476
|
+
Backend_t *backend;
|
1477
|
+
GetBackend(self, backend);
|
1478
|
+
backend_trace(&backend->base, argc, argv);
|
1479
|
+
return self;
|
1480
|
+
}
|
1481
|
+
|
1482
|
+
VALUE Backend_trace_proc_set(VALUE self, VALUE block) {
|
1483
|
+
Backend_t *backend;
|
1484
|
+
GetBackend(self, backend);
|
1485
|
+
|
1486
|
+
backend->base.trace_proc = block;
|
1487
|
+
return self;
|
1488
|
+
}
|
1489
|
+
|
1115
1490
|
void Init_Backend() {
|
1116
1491
|
ev_set_allocator(xrealloc);
|
1117
1492
|
|
@@ -1121,11 +1496,16 @@ void Init_Backend() {
|
|
1121
1496
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
1122
1497
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
1123
1498
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
1499
|
+
rb_define_method(cBackend, "trace", Backend_trace, -1);
|
1500
|
+
rb_define_method(cBackend, "trace_proc=", Backend_trace_proc_set, 1);
|
1124
1501
|
|
1125
|
-
rb_define_method(cBackend, "poll", Backend_poll,
|
1502
|
+
rb_define_method(cBackend, "poll", Backend_poll, 1);
|
1126
1503
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1127
1504
|
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
1128
1505
|
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
1506
|
+
rb_define_method(cBackend, "idle_gc_period=", Backend_idle_gc_period_set, 1);
|
1507
|
+
rb_define_method(cBackend, "idle_proc=", Backend_idle_proc_set, 1);
|
1508
|
+
rb_define_method(cBackend, "splice_chunks", Backend_splice_chunks, 7);
|
1129
1509
|
|
1130
1510
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1131
1511
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
@@ -1143,6 +1523,9 @@ void Init_Backend() {
|
|
1143
1523
|
#ifdef POLYPHONY_LINUX
|
1144
1524
|
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1145
1525
|
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
1526
|
+
#else
|
1527
|
+
rb_define_method(cBackend, "splice", Backend_fake_splice, 3);
|
1528
|
+
rb_define_method(cBackend, "splice_to_eof", Backend_fake_splice_to_eof, 3);
|
1146
1529
|
#endif
|
1147
1530
|
|
1148
1531
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
@@ -1152,7 +1535,6 @@ void Init_Backend() {
|
|
1152
1535
|
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1153
1536
|
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1154
1537
|
|
1155
|
-
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
1156
1538
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
1157
1539
|
|
1158
1540
|
SYM_send = ID2SYM(rb_intern("send"));
|