polyphony 0.52.0 → 0.55.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 +45 -22
- data/Gemfile.lock +3 -1
- data/TODO.md +36 -11
- data/examples/core/queue.rb +19 -0
- data/examples/io/echo_server.rb +1 -0
- data/examples/io/https_server.rb +30 -0
- data/examples/io/stdio.rb +8 -0
- data/examples/io/tcp_proxy.rb +2 -2
- data/ext/polyphony/backend_common.h +10 -10
- data/ext/polyphony/backend_io_uring.c +251 -85
- data/ext/polyphony/backend_io_uring_context.c +15 -2
- data/ext/polyphony/backend_io_uring_context.h +12 -11
- data/ext/polyphony/backend_libev.c +165 -24
- data/ext/polyphony/extconf.rb +3 -1
- data/ext/polyphony/polyphony.c +10 -2
- data/ext/polyphony/polyphony.h +5 -0
- data/ext/polyphony/polyphony_ext.c +3 -0
- data/ext/polyphony/runqueue.c +29 -1
- data/ext/polyphony/socket_extensions.c +33 -0
- data/ext/polyphony/thread.c +22 -6
- data/lib/polyphony/core/sync.rb +8 -0
- data/lib/polyphony/extensions/io.rb +8 -0
- data/lib/polyphony/extensions/openssl.rb +24 -17
- data/lib/polyphony/extensions/socket.rb +30 -35
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -0
- data/test/helper.rb +3 -3
- data/test/test_backend.rb +164 -1
- 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.rb +4 -0
- data/test/test_thread_pool.rb +1 -1
- data/test/test_timer.rb +13 -7
- metadata +20 -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"
|
@@ -10,10 +11,12 @@ const char *op_type_to_str(enum op_type type) {
|
|
10
11
|
case OP_WRITE: return "WRITE";
|
11
12
|
case OP_RECV: return "RECV";
|
12
13
|
case OP_SEND: return "SEND";
|
14
|
+
case OP_SPLICE: return "SPLICE";
|
13
15
|
case OP_TIMEOUT: return "TIMEOUT";
|
14
16
|
case OP_POLL: return "POLL";
|
15
17
|
case OP_ACCEPT: return "ACCEPT";
|
16
18
|
case OP_CONNECT: return "CONNECT";
|
19
|
+
case OP_CHAIN: return "CHAIN";
|
17
20
|
default: return "";
|
18
21
|
};
|
19
22
|
}
|
@@ -34,6 +37,7 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
34
37
|
ctx = malloc(sizeof(op_context_t));
|
35
38
|
}
|
36
39
|
ctx->id = (++store->last_id);
|
40
|
+
// printf("acquire %d (%s)\n", ctx->id, op_type_to_str(type));
|
37
41
|
|
38
42
|
ctx->prev = NULL;
|
39
43
|
ctx->next = store->taken;
|
@@ -43,13 +47,21 @@ inline op_context_t *context_store_acquire(op_context_store_t *store, enum op_ty
|
|
43
47
|
ctx->type = type;
|
44
48
|
ctx->fiber = rb_fiber_current();
|
45
49
|
ctx->resume_value = Qnil;
|
46
|
-
ctx->
|
50
|
+
ctx->ref_count = 2;
|
47
51
|
ctx->result = 0;
|
48
52
|
|
49
53
|
return ctx;
|
50
54
|
}
|
51
55
|
|
52
|
-
|
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
|
+
|
53
65
|
if (ctx->next) ctx->next->prev = ctx->prev;
|
54
66
|
if (ctx->prev) ctx->prev->next = ctx->next;
|
55
67
|
if (store->taken == ctx) store->taken = ctx->next;
|
@@ -58,6 +70,7 @@ inline void context_store_release(op_context_store_t *store, op_context_t *ctx)
|
|
58
70
|
ctx->next = store->available;
|
59
71
|
if (ctx->next) ctx->next->prev = ctx;
|
60
72
|
store->available = ctx;
|
73
|
+
return 1;
|
61
74
|
}
|
62
75
|
|
63
76
|
void context_store_free(op_context_store_t *store) {
|
@@ -10,17 +10,19 @@ enum op_type {
|
|
10
10
|
OP_WRITE,
|
11
11
|
OP_RECV,
|
12
12
|
OP_SEND,
|
13
|
+
OP_SPLICE,
|
13
14
|
OP_TIMEOUT,
|
14
15
|
OP_POLL,
|
15
16
|
OP_ACCEPT,
|
16
|
-
OP_CONNECT
|
17
|
+
OP_CONNECT,
|
18
|
+
OP_CHAIN
|
17
19
|
};
|
18
20
|
|
19
21
|
typedef struct op_context {
|
20
22
|
struct op_context *prev;
|
21
23
|
struct op_context *next;
|
22
24
|
enum op_type type: 16;
|
23
|
-
int
|
25
|
+
unsigned int ref_count : 16;
|
24
26
|
int id;
|
25
27
|
int result;
|
26
28
|
VALUE fiber;
|
@@ -37,17 +39,16 @@ const char *op_type_to_str(enum op_type type);
|
|
37
39
|
|
38
40
|
void context_store_initialize(op_context_store_t *store);
|
39
41
|
op_context_t *context_store_acquire(op_context_store_t *store, enum op_type type);
|
40
|
-
|
42
|
+
int context_store_release(op_context_store_t *store, op_context_t *ctx);
|
41
43
|
void context_store_free(op_context_store_t *store);
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
if (ctx->
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
} \
|
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;
|
51
52
|
}
|
52
53
|
|
53
54
|
#endif /* BACKEND_IO_URING_CONTEXT_H */
|
@@ -38,11 +38,15 @@ thread.
|
|
38
38
|
|
39
39
|
#ifdef POLYPHONY_BACKEND_LIBEV
|
40
40
|
|
41
|
+
#ifdef POLYPHONY_LINUX
|
42
|
+
#define _GNU_SOURCE 1
|
43
|
+
#endif
|
44
|
+
|
45
|
+
#include <fcntl.h>
|
41
46
|
#include <netdb.h>
|
42
47
|
#include <sys/socket.h>
|
43
48
|
#include <sys/uio.h>
|
44
49
|
#include <unistd.h>
|
45
|
-
#include <fcntl.h>
|
46
50
|
#include <netinet/in.h>
|
47
51
|
#include <arpa/inet.h>
|
48
52
|
#include <stdnoreturn.h>
|
@@ -54,6 +58,9 @@ thread.
|
|
54
58
|
#include "ruby/io.h"
|
55
59
|
|
56
60
|
VALUE SYM_libev;
|
61
|
+
VALUE SYM_send;
|
62
|
+
VALUE SYM_splice;
|
63
|
+
VALUE SYM_write;
|
57
64
|
|
58
65
|
ID ID_ivar_is_nonblocking;
|
59
66
|
|
@@ -83,7 +90,6 @@ typedef struct Backend_t {
|
|
83
90
|
// common fields
|
84
91
|
unsigned int currently_polling;
|
85
92
|
unsigned int pending_count;
|
86
|
-
unsigned int poll_no_wait_count;
|
87
93
|
|
88
94
|
// implementation-specific fields
|
89
95
|
struct ev_loop *ev_loop;
|
@@ -138,7 +144,6 @@ static VALUE Backend_initialize(VALUE self) {
|
|
138
144
|
|
139
145
|
backend->currently_polling = 0;
|
140
146
|
backend->pending_count = 0;
|
141
|
-
backend->poll_no_wait_count = 0;
|
142
147
|
|
143
148
|
return Qnil;
|
144
149
|
}
|
@@ -177,23 +182,12 @@ unsigned int Backend_pending_count(VALUE self) {
|
|
177
182
|
}
|
178
183
|
|
179
184
|
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue) {
|
180
|
-
int is_nowait = nowait == Qtrue;
|
181
185
|
Backend_t *backend;
|
182
186
|
GetBackend(self, backend);
|
183
187
|
|
184
|
-
if (is_nowait) {
|
185
|
-
backend->poll_no_wait_count++;
|
186
|
-
if (backend->poll_no_wait_count < 10) return self;
|
187
|
-
|
188
|
-
long runnable_count = Runqueue_len(runqueue);
|
189
|
-
if (backend->poll_no_wait_count < runnable_count) return self;
|
190
|
-
}
|
191
|
-
|
192
|
-
backend->poll_no_wait_count = 0;
|
193
|
-
|
194
188
|
COND_TRACE(2, SYM_fiber_event_poll_enter, current_fiber);
|
195
189
|
backend->currently_polling = 1;
|
196
|
-
ev_run(backend->ev_loop,
|
190
|
+
ev_run(backend->ev_loop, nowait == Qtrue ? EVRUN_NOWAIT : EVRUN_ONCE);
|
197
191
|
backend->currently_polling = 0;
|
198
192
|
COND_TRACE(2, SYM_fiber_event_poll_leave, current_fiber);
|
199
193
|
|
@@ -769,6 +763,118 @@ error:
|
|
769
763
|
return RAISE_EXCEPTION(switchpoint_result);
|
770
764
|
}
|
771
765
|
|
766
|
+
#ifdef POLYPHONY_LINUX
|
767
|
+
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
768
|
+
Backend_t *backend;
|
769
|
+
struct libev_io watcher;
|
770
|
+
VALUE switchpoint_result = Qnil;
|
771
|
+
VALUE underlying_io;
|
772
|
+
rb_io_t *src_fptr;
|
773
|
+
rb_io_t *dest_fptr;
|
774
|
+
int len;
|
775
|
+
|
776
|
+
GetBackend(self, backend);
|
777
|
+
|
778
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
779
|
+
if (underlying_io != Qnil) src = underlying_io;
|
780
|
+
GetOpenFile(src, src_fptr);
|
781
|
+
io_set_nonblock(src_fptr, src);
|
782
|
+
|
783
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
784
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
785
|
+
dest = rb_io_get_write_io(dest);
|
786
|
+
GetOpenFile(dest, dest_fptr);
|
787
|
+
io_set_nonblock(dest_fptr, dest);
|
788
|
+
|
789
|
+
watcher.fiber = Qnil;
|
790
|
+
while (1) {
|
791
|
+
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
792
|
+
if (len < 0) {
|
793
|
+
int e = errno;
|
794
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
795
|
+
|
796
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
797
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
798
|
+
|
799
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
800
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
801
|
+
}
|
802
|
+
else {
|
803
|
+
break;
|
804
|
+
}
|
805
|
+
}
|
806
|
+
|
807
|
+
if (watcher.fiber == Qnil) {
|
808
|
+
switchpoint_result = backend_snooze();
|
809
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
810
|
+
}
|
811
|
+
|
812
|
+
RB_GC_GUARD(watcher.fiber);
|
813
|
+
RB_GC_GUARD(switchpoint_result);
|
814
|
+
|
815
|
+
return INT2NUM(len);
|
816
|
+
error:
|
817
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
818
|
+
}
|
819
|
+
|
820
|
+
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
821
|
+
Backend_t *backend;
|
822
|
+
struct libev_io watcher;
|
823
|
+
VALUE switchpoint_result = Qnil;
|
824
|
+
VALUE underlying_io;
|
825
|
+
rb_io_t *src_fptr;
|
826
|
+
rb_io_t *dest_fptr;
|
827
|
+
int len;
|
828
|
+
int total = 0;
|
829
|
+
|
830
|
+
GetBackend(self, backend);
|
831
|
+
|
832
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
833
|
+
if (underlying_io != Qnil) src = underlying_io;
|
834
|
+
GetOpenFile(src, src_fptr);
|
835
|
+
io_set_nonblock(src_fptr, src);
|
836
|
+
|
837
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
838
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
839
|
+
dest = rb_io_get_write_io(dest);
|
840
|
+
GetOpenFile(dest, dest_fptr);
|
841
|
+
io_set_nonblock(dest_fptr, dest);
|
842
|
+
|
843
|
+
watcher.fiber = Qnil;
|
844
|
+
while (1) {
|
845
|
+
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
846
|
+
if (len < 0) {
|
847
|
+
int e = errno;
|
848
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
849
|
+
|
850
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
851
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
852
|
+
|
853
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
854
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
855
|
+
}
|
856
|
+
else if (len == 0) {
|
857
|
+
break;
|
858
|
+
}
|
859
|
+
else {
|
860
|
+
total += len;
|
861
|
+
}
|
862
|
+
}
|
863
|
+
|
864
|
+
if (watcher.fiber == Qnil) {
|
865
|
+
switchpoint_result = backend_snooze();
|
866
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
867
|
+
}
|
868
|
+
|
869
|
+
RB_GC_GUARD(watcher.fiber);
|
870
|
+
RB_GC_GUARD(switchpoint_result);
|
871
|
+
|
872
|
+
return INT2NUM(total);
|
873
|
+
error:
|
874
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
875
|
+
}
|
876
|
+
#endif
|
877
|
+
|
772
878
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
773
879
|
Backend_t *backend;
|
774
880
|
rb_io_t *fptr;
|
@@ -981,6 +1087,31 @@ VALUE Backend_kind(VALUE self) {
|
|
981
1087
|
return SYM_libev;
|
982
1088
|
}
|
983
1089
|
|
1090
|
+
VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
1091
|
+
VALUE result = Qnil;
|
1092
|
+
if (argc == 0) return result;
|
1093
|
+
|
1094
|
+
for (int i = 0; i < argc; i++) {
|
1095
|
+
VALUE op = argv[i];
|
1096
|
+
VALUE op_type = RARRAY_AREF(op, 0);
|
1097
|
+
VALUE op_len = RARRAY_LEN(op);
|
1098
|
+
|
1099
|
+
if (op_type == SYM_write && op_len == 3)
|
1100
|
+
result = Backend_write(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
|
1101
|
+
else if (op_type == SYM_send && op_len == 4)
|
1102
|
+
result = Backend_send(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1103
|
+
#ifdef POLYPHONY_LINUX
|
1104
|
+
else if (op_type == SYM_splice && op_len == 4)
|
1105
|
+
result = Backend_splice(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1106
|
+
#endif
|
1107
|
+
else
|
1108
|
+
rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
RB_GC_GUARD(result);
|
1112
|
+
return result;
|
1113
|
+
}
|
1114
|
+
|
984
1115
|
void Init_Backend() {
|
985
1116
|
ev_set_allocator(xrealloc);
|
986
1117
|
|
@@ -993,30 +1124,40 @@ void Init_Backend() {
|
|
993
1124
|
|
994
1125
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
995
1126
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1127
|
+
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
1128
|
+
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
996
1129
|
|
997
|
-
rb_define_method(cBackend, "read", Backend_read, 4);
|
998
|
-
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
999
|
-
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
1000
|
-
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1001
1130
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1002
1131
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
1003
1132
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
1133
|
+
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
1134
|
+
rb_define_method(cBackend, "read", Backend_read, 4);
|
1135
|
+
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
1004
1136
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
1005
1137
|
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
|
1006
1138
|
rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
|
1007
1139
|
rb_define_method(cBackend, "send", Backend_send, 3);
|
1008
1140
|
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
1009
|
-
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1010
1141
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
1011
|
-
|
1142
|
+
|
1143
|
+
#ifdef POLYPHONY_LINUX
|
1144
|
+
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1145
|
+
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
1146
|
+
#endif
|
1147
|
+
|
1012
1148
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
1013
|
-
rb_define_method(cBackend, "
|
1149
|
+
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
1014
1150
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
1015
|
-
|
1016
|
-
rb_define_method(cBackend, "
|
1151
|
+
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1152
|
+
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1153
|
+
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
1017
1154
|
|
1018
1155
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
1019
1156
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
1157
|
+
|
1158
|
+
SYM_send = ID2SYM(rb_intern("send"));
|
1159
|
+
SYM_splice = ID2SYM(rb_intern("splice"));
|
1160
|
+
SYM_write = ID2SYM(rb_intern("write"));
|
1020
1161
|
}
|
1021
1162
|
|
1022
1163
|
#endif // POLYPHONY_BACKEND_LIBEV
|
data/ext/polyphony/extconf.rb
CHANGED
@@ -6,8 +6,9 @@ require 'mkmf'
|
|
6
6
|
use_liburing = false
|
7
7
|
use_pidfd_open = false
|
8
8
|
force_use_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
|
9
|
+
linux = RUBY_PLATFORM =~ /linux/
|
9
10
|
|
10
|
-
if
|
11
|
+
if linux && `uname -sr` =~ /Linux 5\.([\d+])/
|
11
12
|
kernel_minor_version = $1.gsub('.', '').to_i
|
12
13
|
use_liburing = !force_use_libev && kernel_minor_version >= 6
|
13
14
|
use_pidfd_open = kernel_minor_version >= 3
|
@@ -20,6 +21,7 @@ if use_liburing
|
|
20
21
|
$CFLAGS << " -Wno-pointer-arith"
|
21
22
|
else
|
22
23
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
24
|
+
$defs << "-DPOLYPHONY_LINUX" if linux
|
23
25
|
$defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
|
24
26
|
$defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
|
25
27
|
$defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -46,8 +46,6 @@ VALUE Polyphony_trace(VALUE self, VALUE enabled) {
|
|
46
46
|
return Qnil;
|
47
47
|
}
|
48
48
|
|
49
|
-
#define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
|
50
|
-
|
51
49
|
VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
52
50
|
return Backend_accept(BACKEND(), server_socket, socket_class);
|
53
51
|
}
|
@@ -96,6 +94,14 @@ VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
|
|
96
94
|
return Backend_sleep(BACKEND(), duration);
|
97
95
|
}
|
98
96
|
|
97
|
+
VALUE Polyphony_backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
98
|
+
return Backend_splice(BACKEND(), src, dest, maxlen);
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE Polyphony_backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize) {
|
102
|
+
return Backend_splice_to_eof(BACKEND(), src, dest, chunksize);
|
103
|
+
}
|
104
|
+
|
99
105
|
VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
|
100
106
|
return Backend_timeout(argc, argv, BACKEND());
|
101
107
|
}
|
@@ -138,6 +144,8 @@ void Init_Polyphony() {
|
|
138
144
|
rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
|
139
145
|
rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
|
140
146
|
rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
|
147
|
+
rb_define_singleton_method(mPolyphony, "backend_splice", Polyphony_backend_splice, 3);
|
148
|
+
rb_define_singleton_method(mPolyphony, "backend_splice_to_eof", Polyphony_backend_splice_to_eof, 3);
|
141
149
|
rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
|
142
150
|
rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
|
143
151
|
rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -31,6 +31,8 @@
|
|
31
31
|
// Fiber#transfer
|
32
32
|
#define FIBER_TRANSFER(fiber, value) rb_funcall(fiber, ID_transfer, 1, value)
|
33
33
|
|
34
|
+
#define BACKEND() (rb_ivar_get(rb_thread_current(), ID_ivar_backend))
|
35
|
+
|
34
36
|
extern VALUE mPolyphony;
|
35
37
|
extern VALUE cQueue;
|
36
38
|
extern VALUE cEvent;
|
@@ -88,6 +90,7 @@ int Runqueue_index_of(VALUE self, VALUE fiber);
|
|
88
90
|
void Runqueue_clear(VALUE self);
|
89
91
|
long Runqueue_len(VALUE self);
|
90
92
|
int Runqueue_empty_p(VALUE self);
|
93
|
+
int Runqueue_should_poll_nonblocking(VALUE self);
|
91
94
|
|
92
95
|
#ifdef POLYPHONY_BACKEND_LIBEV
|
93
96
|
#define Backend_recv_loop Backend_read_loop
|
@@ -108,6 +111,8 @@ VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method)
|
|
108
111
|
VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
|
109
112
|
VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
|
110
113
|
VALUE Backend_sleep(VALUE self, VALUE duration);
|
114
|
+
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
115
|
+
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize);
|
111
116
|
VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
|
112
117
|
VALUE Backend_timer_loop(VALUE self, VALUE interval);
|
113
118
|
VALUE Backend_wait_event(VALUE self, VALUE raise);
|