polyphony 0.50.1 → 0.53.2
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/CHANGELOG.md +23 -0
- data/Gemfile.lock +7 -68
- data/TODO.md +37 -6
- data/examples/core/forking.rb +2 -2
- data/examples/io/echo_server.rb +1 -0
- data/examples/io/tcp_proxy.rb +2 -2
- data/ext/polyphony/backend_common.h +36 -6
- data/ext/polyphony/backend_io_uring.c +216 -21
- data/ext/polyphony/backend_io_uring_context.c +1 -0
- data/ext/polyphony/backend_io_uring_context.h +1 -0
- data/ext/polyphony/backend_libev.c +362 -20
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/extconf.rb +9 -2
- data/ext/polyphony/polyphony.c +102 -0
- data/ext/polyphony/polyphony.h +32 -2
- data/ext/polyphony/polyphony_ext.c +3 -0
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +1 -1
- data/ext/polyphony/socket_extensions.c +33 -0
- data/ext/polyphony/thread.c +8 -2
- data/lib/polyphony/adapters/irb.rb +1 -1
- data/lib/polyphony/adapters/mysql2.rb +1 -1
- data/lib/polyphony/adapters/postgres.rb +5 -5
- data/lib/polyphony/adapters/process.rb +4 -4
- data/lib/polyphony/core/global_api.rb +5 -5
- data/lib/polyphony/core/sync.rb +1 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/core.rb +1 -1
- data/lib/polyphony/extensions/io.rb +21 -22
- data/lib/polyphony/extensions/openssl.rb +6 -6
- data/lib/polyphony/extensions/socket.rb +56 -47
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +6 -5
- data/test/helper.rb +1 -1
- data/test/stress.rb +2 -0
- data/test/test_backend.rb +152 -5
- data/test/test_global_api.rb +2 -2
- data/test/test_io.rb +84 -1
- data/test/test_kernel.rb +1 -1
- data/test/test_signal.rb +1 -1
- data/test/test_socket.rb +61 -0
- data/test/test_thread.rb +4 -0
- data/test/test_timer.rb +1 -1
- metadata +19 -60
@@ -10,6 +10,7 @@ const char *op_type_to_str(enum op_type type) {
|
|
10
10
|
case OP_WRITE: return "WRITE";
|
11
11
|
case OP_RECV: return "RECV";
|
12
12
|
case OP_SEND: return "SEND";
|
13
|
+
case OP_SPLICE: return "SPLICE";
|
13
14
|
case OP_TIMEOUT: return "TIMEOUT";
|
14
15
|
case OP_POLL: return "POLL";
|
15
16
|
case OP_ACCEPT: return "ACCEPT";
|
@@ -1,10 +1,52 @@
|
|
1
|
+
/*
|
2
|
+
# Libev-based blocking ops backend for Polyphony
|
3
|
+
|
4
|
+
## Backend initialization
|
5
|
+
|
6
|
+
The backend is initialized by creating an event loop. For the main thread the
|
7
|
+
default event loop is used, but we since we don't need to handle any signals
|
8
|
+
(see the waitpid implementation below) we might as well use a non-default event
|
9
|
+
loop for the main thread at some time in the future.
|
10
|
+
|
11
|
+
In addition, we create an async watcher that is used for interrupting the #poll
|
12
|
+
method from another thread.
|
13
|
+
|
14
|
+
## Blocking operations
|
15
|
+
|
16
|
+
I/O operations start by making sure the io has been set to non-blocking
|
17
|
+
operation (O_NONBLOCK). That way, if the syscall would block, we'd get an
|
18
|
+
EWOULDBLOCK or EAGAIN instead of blocking.
|
19
|
+
|
20
|
+
Once the OS has indicated that the operation would block, we start a watcher
|
21
|
+
(its type corresponding to the desired operation), and call ev_xxxx_start. in We
|
22
|
+
then call Thread_switch_fiber and switch to another fiber while waiting for the
|
23
|
+
watcher to be triggered.
|
24
|
+
|
25
|
+
## Polling for events
|
26
|
+
|
27
|
+
Backend_poll is called either once the corresponding thread has no more work to
|
28
|
+
do (no runnable fibers) or periodically while the thread is scheduling fibers in
|
29
|
+
order to prevent event starvation.
|
30
|
+
|
31
|
+
## Behaviour of waitpid
|
32
|
+
|
33
|
+
On Linux 5.3+, pidfd_open will be used, otherwise a libev child watcher will be
|
34
|
+
used. Note that if a child watcher is used, waitpid will only work from the main
|
35
|
+
thread.
|
36
|
+
|
37
|
+
*/
|
38
|
+
|
1
39
|
#ifdef POLYPHONY_BACKEND_LIBEV
|
2
40
|
|
41
|
+
#ifdef POLYPHONY_LINUX
|
42
|
+
#define _GNU_SOURCE 1
|
43
|
+
#endif
|
44
|
+
|
45
|
+
#include <fcntl.h>
|
3
46
|
#include <netdb.h>
|
4
47
|
#include <sys/socket.h>
|
5
48
|
#include <sys/uio.h>
|
6
49
|
#include <unistd.h>
|
7
|
-
#include <fcntl.h>
|
8
50
|
#include <netinet/in.h>
|
9
51
|
#include <arpa/inet.h>
|
10
52
|
#include <stdnoreturn.h>
|
@@ -16,6 +58,9 @@
|
|
16
58
|
#include "ruby/io.h"
|
17
59
|
|
18
60
|
VALUE SYM_libev;
|
61
|
+
VALUE SYM_send;
|
62
|
+
VALUE SYM_splice;
|
63
|
+
VALUE SYM_write;
|
19
64
|
|
20
65
|
ID ID_ivar_is_nonblocking;
|
21
66
|
|
@@ -76,17 +121,27 @@ void break_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
|
|
76
121
|
// of a *blocking* event loop (waking it up) in a thread-safe, signal-safe manner
|
77
122
|
}
|
78
123
|
|
124
|
+
inline struct ev_loop *libev_new_loop() {
|
125
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
126
|
+
return ev_loop_new(EVFLAG_NOSIGMASK);
|
127
|
+
#else
|
128
|
+
int is_main_thread = (rb_thread_current() == rb_thread_main());
|
129
|
+
return is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
|
130
|
+
#endif
|
131
|
+
}
|
132
|
+
|
79
133
|
static VALUE Backend_initialize(VALUE self) {
|
80
134
|
Backend_t *backend;
|
81
|
-
|
82
|
-
int is_main_thread = (thread == rb_thread_main());
|
83
|
-
|
135
|
+
|
84
136
|
GetBackend(self, backend);
|
85
|
-
backend->ev_loop =
|
137
|
+
backend->ev_loop = libev_new_loop();
|
86
138
|
|
139
|
+
// start async watcher used for breaking a poll op (from another thread)
|
87
140
|
ev_async_init(&backend->break_async, break_async_callback);
|
88
141
|
ev_async_start(backend->ev_loop, &backend->break_async);
|
89
|
-
|
142
|
+
// the break_async watcher is unreferenced, in order for Backend_poll to not
|
143
|
+
// block when no other watcher is active
|
144
|
+
ev_unref(backend->ev_loop);
|
90
145
|
|
91
146
|
backend->currently_polling = 0;
|
92
147
|
backend->pending_count = 0;
|
@@ -334,6 +389,58 @@ error:
|
|
334
389
|
return RAISE_EXCEPTION(switchpoint_result);
|
335
390
|
}
|
336
391
|
|
392
|
+
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
393
|
+
Backend_t *backend;
|
394
|
+
struct libev_io watcher;
|
395
|
+
rb_io_t *fptr;
|
396
|
+
VALUE str;
|
397
|
+
long total;
|
398
|
+
long len = 8192;
|
399
|
+
int shrinkable;
|
400
|
+
char *buf;
|
401
|
+
VALUE switchpoint_result = Qnil;
|
402
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
403
|
+
ID method_id = SYM2ID(method);
|
404
|
+
|
405
|
+
READ_LOOP_PREPARE_STR();
|
406
|
+
|
407
|
+
GetBackend(self, backend);
|
408
|
+
if (underlying_io != Qnil) io = underlying_io;
|
409
|
+
GetOpenFile(io, fptr);
|
410
|
+
rb_io_check_byte_readable(fptr);
|
411
|
+
io_set_nonblock(fptr, io);
|
412
|
+
rectify_io_file_pos(fptr);
|
413
|
+
watcher.fiber = Qnil;
|
414
|
+
|
415
|
+
while (1) {
|
416
|
+
ssize_t n = read(fptr->fd, buf, len);
|
417
|
+
if (n < 0) {
|
418
|
+
int e = errno;
|
419
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
420
|
+
|
421
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_READ);
|
422
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
423
|
+
}
|
424
|
+
else {
|
425
|
+
switchpoint_result = backend_snooze();
|
426
|
+
|
427
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
428
|
+
|
429
|
+
if (n == 0) break; // EOF
|
430
|
+
total = n;
|
431
|
+
READ_LOOP_PASS_STR_TO_RECEIVER(receiver, method_id);
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
RB_GC_GUARD(str);
|
436
|
+
RB_GC_GUARD(watcher.fiber);
|
437
|
+
RB_GC_GUARD(switchpoint_result);
|
438
|
+
|
439
|
+
return io;
|
440
|
+
error:
|
441
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
442
|
+
}
|
443
|
+
|
337
444
|
VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
338
445
|
Backend_t *backend;
|
339
446
|
struct libev_io watcher;
|
@@ -620,6 +727,167 @@ error:
|
|
620
727
|
return RAISE_EXCEPTION(switchpoint_result);
|
621
728
|
}
|
622
729
|
|
730
|
+
VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
731
|
+
Backend_t *backend;
|
732
|
+
struct libev_io watcher;
|
733
|
+
rb_io_t *fptr;
|
734
|
+
VALUE switchpoint_result = Qnil;
|
735
|
+
VALUE underlying_io;
|
736
|
+
char *buf = StringValuePtr(str);
|
737
|
+
long len = RSTRING_LEN(str);
|
738
|
+
long left = len;
|
739
|
+
int flags_int = NUM2INT(flags);
|
740
|
+
|
741
|
+
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
742
|
+
if (underlying_io != Qnil) io = underlying_io;
|
743
|
+
GetBackend(self, backend);
|
744
|
+
io = rb_io_get_write_io(io);
|
745
|
+
GetOpenFile(io, fptr);
|
746
|
+
io_set_nonblock(fptr, io);
|
747
|
+
watcher.fiber = Qnil;
|
748
|
+
|
749
|
+
while (left > 0) {
|
750
|
+
ssize_t n = send(fptr->fd, buf, left, flags_int);
|
751
|
+
if (n < 0) {
|
752
|
+
int e = errno;
|
753
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
754
|
+
|
755
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
|
756
|
+
|
757
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
758
|
+
}
|
759
|
+
else {
|
760
|
+
buf += n;
|
761
|
+
left -= n;
|
762
|
+
}
|
763
|
+
}
|
764
|
+
|
765
|
+
if (watcher.fiber == Qnil) {
|
766
|
+
switchpoint_result = backend_snooze();
|
767
|
+
|
768
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
769
|
+
}
|
770
|
+
|
771
|
+
RB_GC_GUARD(watcher.fiber);
|
772
|
+
RB_GC_GUARD(switchpoint_result);
|
773
|
+
|
774
|
+
return INT2NUM(len);
|
775
|
+
error:
|
776
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
777
|
+
}
|
778
|
+
|
779
|
+
#ifdef POLYPHONY_LINUX
|
780
|
+
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
781
|
+
Backend_t *backend;
|
782
|
+
struct libev_io watcher;
|
783
|
+
VALUE switchpoint_result = Qnil;
|
784
|
+
VALUE underlying_io;
|
785
|
+
rb_io_t *src_fptr;
|
786
|
+
rb_io_t *dest_fptr;
|
787
|
+
int len;
|
788
|
+
|
789
|
+
GetBackend(self, backend);
|
790
|
+
|
791
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
792
|
+
if (underlying_io != Qnil) src = underlying_io;
|
793
|
+
GetOpenFile(src, src_fptr);
|
794
|
+
io_set_nonblock(src_fptr, src);
|
795
|
+
|
796
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
797
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
798
|
+
dest = rb_io_get_write_io(dest);
|
799
|
+
GetOpenFile(dest, dest_fptr);
|
800
|
+
io_set_nonblock(dest_fptr, dest);
|
801
|
+
|
802
|
+
watcher.fiber = Qnil;
|
803
|
+
while (1) {
|
804
|
+
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
805
|
+
if (len < 0) {
|
806
|
+
int e = errno;
|
807
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
808
|
+
|
809
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
810
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
811
|
+
|
812
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
813
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
814
|
+
}
|
815
|
+
else {
|
816
|
+
break;
|
817
|
+
}
|
818
|
+
}
|
819
|
+
|
820
|
+
if (watcher.fiber == Qnil) {
|
821
|
+
switchpoint_result = backend_snooze();
|
822
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
823
|
+
}
|
824
|
+
|
825
|
+
RB_GC_GUARD(watcher.fiber);
|
826
|
+
RB_GC_GUARD(switchpoint_result);
|
827
|
+
|
828
|
+
return INT2NUM(len);
|
829
|
+
error:
|
830
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
831
|
+
}
|
832
|
+
|
833
|
+
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
834
|
+
Backend_t *backend;
|
835
|
+
struct libev_io watcher;
|
836
|
+
VALUE switchpoint_result = Qnil;
|
837
|
+
VALUE underlying_io;
|
838
|
+
rb_io_t *src_fptr;
|
839
|
+
rb_io_t *dest_fptr;
|
840
|
+
int len;
|
841
|
+
int total = 0;
|
842
|
+
|
843
|
+
GetBackend(self, backend);
|
844
|
+
|
845
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
846
|
+
if (underlying_io != Qnil) src = underlying_io;
|
847
|
+
GetOpenFile(src, src_fptr);
|
848
|
+
io_set_nonblock(src_fptr, src);
|
849
|
+
|
850
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
851
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
852
|
+
dest = rb_io_get_write_io(dest);
|
853
|
+
GetOpenFile(dest, dest_fptr);
|
854
|
+
io_set_nonblock(dest_fptr, dest);
|
855
|
+
|
856
|
+
watcher.fiber = Qnil;
|
857
|
+
while (1) {
|
858
|
+
len = splice(src_fptr->fd, 0, dest_fptr->fd, 0, NUM2INT(maxlen), 0);
|
859
|
+
if (len < 0) {
|
860
|
+
int e = errno;
|
861
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
862
|
+
|
863
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, src_fptr->fd, &watcher, EV_READ);
|
864
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
865
|
+
|
866
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, dest_fptr->fd, &watcher, EV_WRITE);
|
867
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
868
|
+
}
|
869
|
+
else if (len == 0) {
|
870
|
+
break;
|
871
|
+
}
|
872
|
+
else {
|
873
|
+
total += len;
|
874
|
+
}
|
875
|
+
}
|
876
|
+
|
877
|
+
if (watcher.fiber == Qnil) {
|
878
|
+
switchpoint_result = backend_snooze();
|
879
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
880
|
+
}
|
881
|
+
|
882
|
+
RB_GC_GUARD(watcher.fiber);
|
883
|
+
RB_GC_GUARD(switchpoint_result);
|
884
|
+
|
885
|
+
return INT2NUM(total);
|
886
|
+
error:
|
887
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
888
|
+
}
|
889
|
+
#endif
|
890
|
+
|
623
891
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
624
892
|
Backend_t *backend;
|
625
893
|
rb_io_t *fptr;
|
@@ -747,6 +1015,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
747
1015
|
return result;
|
748
1016
|
}
|
749
1017
|
|
1018
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
750
1019
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
751
1020
|
int pid_int = NUM2INT(pid);
|
752
1021
|
int fd = pidfd_open(pid_int, 0);
|
@@ -759,18 +1028,53 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
759
1028
|
RAISE_IF_EXCEPTION(resume_value);
|
760
1029
|
RB_GC_GUARD(resume_value);
|
761
1030
|
}
|
1031
|
+
else {
|
1032
|
+
int e = errno;
|
1033
|
+
rb_syserr_fail(e, strerror(e));
|
1034
|
+
}
|
762
1035
|
|
763
1036
|
int status = 0;
|
764
1037
|
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
765
1038
|
if (ret < 0) {
|
766
1039
|
int e = errno;
|
767
|
-
|
768
|
-
ret = pid_int;
|
769
|
-
else
|
770
|
-
rb_syserr_fail(e, strerror(e));
|
1040
|
+
rb_syserr_fail(e, strerror(e));
|
771
1041
|
}
|
772
1042
|
return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
|
773
1043
|
}
|
1044
|
+
#else
|
1045
|
+
struct libev_child {
|
1046
|
+
struct ev_child child;
|
1047
|
+
VALUE fiber;
|
1048
|
+
};
|
1049
|
+
|
1050
|
+
void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
1051
|
+
struct libev_child *watcher = (struct libev_child *)w;
|
1052
|
+
int exit_status = WEXITSTATUS(w->rstatus);
|
1053
|
+
VALUE status;
|
1054
|
+
|
1055
|
+
status = rb_ary_new_from_args(2, INT2NUM(w->rpid), INT2NUM(exit_status));
|
1056
|
+
Fiber_make_runnable(watcher->fiber, status);
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
1060
|
+
Backend_t *backend;
|
1061
|
+
struct libev_child watcher;
|
1062
|
+
VALUE switchpoint_result = Qnil;
|
1063
|
+
GetBackend(self, backend);
|
1064
|
+
|
1065
|
+
watcher.fiber = rb_fiber_current();
|
1066
|
+
ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
|
1067
|
+
ev_child_start(backend->ev_loop, &watcher.child);
|
1068
|
+
|
1069
|
+
switchpoint_result = backend_await(backend);
|
1070
|
+
|
1071
|
+
ev_child_stop(backend->ev_loop, &watcher.child);
|
1072
|
+
RAISE_IF_EXCEPTION(switchpoint_result);
|
1073
|
+
RB_GC_GUARD(watcher.fiber);
|
1074
|
+
RB_GC_GUARD(switchpoint_result);
|
1075
|
+
return switchpoint_result;
|
1076
|
+
}
|
1077
|
+
#endif
|
774
1078
|
|
775
1079
|
void Backend_async_callback(EV_P_ ev_async *w, int revents) { }
|
776
1080
|
|
@@ -796,10 +1100,35 @@ VALUE Backend_kind(VALUE self) {
|
|
796
1100
|
return SYM_libev;
|
797
1101
|
}
|
798
1102
|
|
1103
|
+
VALUE Backend_chain(int argc,VALUE *argv, VALUE self) {
|
1104
|
+
VALUE result = Qnil;
|
1105
|
+
if (argc == 0) return result;
|
1106
|
+
|
1107
|
+
for (int i = 0; i < argc; i++) {
|
1108
|
+
VALUE op = argv[i];
|
1109
|
+
VALUE op_type = RARRAY_AREF(op, 0);
|
1110
|
+
VALUE op_len = RARRAY_LEN(op);
|
1111
|
+
|
1112
|
+
if (op_type == SYM_write && op_len == 3)
|
1113
|
+
result = Backend_write(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2));
|
1114
|
+
else if (op_type == SYM_send && op_len == 4)
|
1115
|
+
result = Backend_send(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1116
|
+
#ifdef POLYPHONY_LINUX
|
1117
|
+
else if (op_type == SYM_splice && op_len == 4)
|
1118
|
+
result = Backend_splice(self, RARRAY_AREF(op, 1), RARRAY_AREF(op, 2), RARRAY_AREF(op, 3));
|
1119
|
+
#endif
|
1120
|
+
else
|
1121
|
+
rb_raise(rb_eRuntimeError, "Invalid op specified or bad op arity");
|
1122
|
+
}
|
1123
|
+
|
1124
|
+
RB_GC_GUARD(result);
|
1125
|
+
return result;
|
1126
|
+
}
|
1127
|
+
|
799
1128
|
void Init_Backend() {
|
800
1129
|
ev_set_allocator(xrealloc);
|
801
1130
|
|
802
|
-
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend",
|
1131
|
+
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
803
1132
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
804
1133
|
|
805
1134
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
@@ -808,27 +1137,40 @@ void Init_Backend() {
|
|
808
1137
|
|
809
1138
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
810
1139
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1140
|
+
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
1141
|
+
rb_define_method(cBackend, "chain", Backend_chain, -1);
|
811
1142
|
|
812
|
-
rb_define_method(cBackend, "read", Backend_read, 4);
|
813
|
-
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
814
|
-
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
815
1143
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
816
1144
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
817
1145
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
1146
|
+
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
1147
|
+
rb_define_method(cBackend, "read", Backend_read, 4);
|
1148
|
+
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
818
1149
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
819
1150
|
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
|
820
|
-
rb_define_method(cBackend, "
|
821
|
-
rb_define_method(cBackend, "
|
1151
|
+
rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
|
1152
|
+
rb_define_method(cBackend, "send", Backend_send, 3);
|
1153
|
+
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
822
1154
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
823
|
-
|
1155
|
+
|
1156
|
+
#ifdef POLYPHONY_LINUX
|
1157
|
+
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1158
|
+
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
1159
|
+
#endif
|
1160
|
+
|
824
1161
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
825
|
-
rb_define_method(cBackend, "
|
1162
|
+
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
826
1163
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
827
|
-
|
828
|
-
rb_define_method(cBackend, "
|
1164
|
+
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1165
|
+
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1166
|
+
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
829
1167
|
|
830
1168
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
831
1169
|
SYM_libev = ID2SYM(rb_intern("libev"));
|
1170
|
+
|
1171
|
+
SYM_send = ID2SYM(rb_intern("send"));
|
1172
|
+
SYM_splice = ID2SYM(rb_intern("splice"));
|
1173
|
+
SYM_write = ID2SYM(rb_intern("write"));
|
832
1174
|
}
|
833
1175
|
|
834
1176
|
#endif // POLYPHONY_BACKEND_LIBEV
|