polyphony 0.51.0 → 0.54.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 +2 -2
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +7 -68
- data/TODO.md +37 -6
- data/examples/core/forking.rb +2 -2
- 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/tcp_proxy.rb +2 -2
- data/ext/polyphony/backend_common.h +29 -6
- data/ext/polyphony/backend_io_uring.c +125 -23
- 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 +309 -21
- 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 +2 -2
- data/lib/polyphony/core/global_api.rb +5 -5
- data/lib/polyphony/core/sync.rb +9 -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 +20 -25
- data/lib/polyphony/extensions/openssl.rb +28 -21
- data/lib/polyphony/extensions/socket.rb +51 -54
- 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 +33 -2
- data/test/test_kernel.rb +1 -1
- data/test/test_signal.rb +1 -1
- data/test/test_socket.rb +27 -0
- data/test/test_sync.rb +43 -0
- data/test/test_thread.rb +4 -0
- data/test/test_timer.rb +1 -1
- metadata +10 -49
@@ -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;
|
@@ -672,6 +727,167 @@ error:
|
|
672
727
|
return RAISE_EXCEPTION(switchpoint_result);
|
673
728
|
}
|
674
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
|
+
|
675
891
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
676
892
|
Backend_t *backend;
|
677
893
|
rb_io_t *fptr;
|
@@ -799,6 +1015,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
799
1015
|
return result;
|
800
1016
|
}
|
801
1017
|
|
1018
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
802
1019
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
803
1020
|
int pid_int = NUM2INT(pid);
|
804
1021
|
int fd = pidfd_open(pid_int, 0);
|
@@ -811,18 +1028,53 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
811
1028
|
RAISE_IF_EXCEPTION(resume_value);
|
812
1029
|
RB_GC_GUARD(resume_value);
|
813
1030
|
}
|
1031
|
+
else {
|
1032
|
+
int e = errno;
|
1033
|
+
rb_syserr_fail(e, strerror(e));
|
1034
|
+
}
|
814
1035
|
|
815
1036
|
int status = 0;
|
816
1037
|
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
817
1038
|
if (ret < 0) {
|
818
1039
|
int e = errno;
|
819
|
-
|
820
|
-
ret = pid_int;
|
821
|
-
else
|
822
|
-
rb_syserr_fail(e, strerror(e));
|
1040
|
+
rb_syserr_fail(e, strerror(e));
|
823
1041
|
}
|
824
1042
|
return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
|
825
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
|
826
1078
|
|
827
1079
|
void Backend_async_callback(EV_P_ ev_async *w, int revents) { }
|
828
1080
|
|
@@ -848,10 +1100,35 @@ VALUE Backend_kind(VALUE self) {
|
|
848
1100
|
return SYM_libev;
|
849
1101
|
}
|
850
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
|
+
|
851
1128
|
void Init_Backend() {
|
852
1129
|
ev_set_allocator(xrealloc);
|
853
1130
|
|
854
|
-
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend",
|
1131
|
+
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
855
1132
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
856
1133
|
|
857
1134
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
@@ -860,29 +1137,40 @@ void Init_Backend() {
|
|
860
1137
|
|
861
1138
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
862
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);
|
863
1142
|
|
864
|
-
rb_define_method(cBackend, "read", Backend_read, 4);
|
865
|
-
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
866
|
-
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
867
|
-
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
868
1143
|
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
869
1144
|
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
870
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);
|
871
1149
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
872
1150
|
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
|
873
1151
|
rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
|
874
|
-
rb_define_method(cBackend, "send",
|
875
|
-
rb_define_method(cBackend, "
|
1152
|
+
rb_define_method(cBackend, "send", Backend_send, 3);
|
1153
|
+
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
876
1154
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
877
|
-
|
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
|
+
|
878
1161
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
879
|
-
rb_define_method(cBackend, "
|
1162
|
+
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
880
1163
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
881
|
-
|
882
|
-
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);
|
883
1167
|
|
884
1168
|
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
885
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"));
|
886
1174
|
}
|
887
1175
|
|
888
1176
|
#endif // POLYPHONY_BACKEND_LIBEV
|
data/ext/polyphony/event.c
CHANGED
@@ -77,7 +77,7 @@ VALUE Event_await(VALUE self) {
|
|
77
77
|
}
|
78
78
|
|
79
79
|
void Init_Event() {
|
80
|
-
cEvent = rb_define_class_under(mPolyphony, "Event",
|
80
|
+
cEvent = rb_define_class_under(mPolyphony, "Event", rb_cObject);
|
81
81
|
rb_define_alloc_func(cEvent, Event_allocate);
|
82
82
|
|
83
83
|
rb_define_method(cEvent, "initialize", Event_initialize, 0);
|
data/ext/polyphony/extconf.rb
CHANGED
@@ -4,18 +4,24 @@ require 'rubygems'
|
|
4
4
|
require 'mkmf'
|
5
5
|
|
6
6
|
use_liburing = false
|
7
|
+
use_pidfd_open = false
|
7
8
|
force_use_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
|
9
|
+
linux = RUBY_PLATFORM =~ /linux/
|
8
10
|
|
9
|
-
if
|
11
|
+
if linux && `uname -sr` =~ /Linux 5\.([\d+])/
|
10
12
|
kernel_minor_version = $1.gsub('.', '').to_i
|
11
|
-
use_liburing = kernel_minor_version >= 6
|
13
|
+
use_liburing = !force_use_libev && kernel_minor_version >= 6
|
14
|
+
use_pidfd_open = kernel_minor_version >= 3
|
12
15
|
end
|
13
16
|
|
17
|
+
$defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if use_pidfd_open
|
14
18
|
if use_liburing
|
15
19
|
$defs << "-DPOLYPHONY_BACKEND_LIBURING"
|
20
|
+
$defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
|
16
21
|
$CFLAGS << " -Wno-pointer-arith"
|
17
22
|
else
|
18
23
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
24
|
+
$defs << "-DPOLYPHONY_LINUX" if linux
|
19
25
|
$defs << '-DEV_USE_LINUXAIO' if have_header('linux/aio_abi.h')
|
20
26
|
$defs << '-DEV_USE_SELECT' if have_header('sys/select.h')
|
21
27
|
$defs << '-DEV_USE_POLL' if have_type('port_event_t', 'poll.h')
|
@@ -23,6 +29,7 @@ else
|
|
23
29
|
$defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
|
24
30
|
$defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
|
25
31
|
$defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
|
32
|
+
|
26
33
|
$CFLAGS << " -Wno-comment"
|
27
34
|
$CFLAGS << " -Wno-unused-result"
|
28
35
|
$CFLAGS << " -Wno-dangling-else"
|