polyphony 0.51.0 → 0.52.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/CHANGELOG.md +10 -0
- data/Gemfile.lock +5 -68
- data/TODO.md +6 -3
- data/examples/core/forking.rb +2 -2
- data/ext/polyphony/backend_common.h +29 -6
- data/ext/polyphony/backend_io_uring.c +49 -5
- data/ext/polyphony/backend_libev.c +145 -11
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/extconf.rb +7 -2
- data/ext/polyphony/polyphony.c +94 -0
- data/ext/polyphony/polyphony.h +28 -2
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +1 -1
- 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 +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 +12 -25
- data/lib/polyphony/extensions/openssl.rb +6 -6
- data/lib/polyphony/extensions/socket.rb +35 -47
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +5 -5
- data/test/helper.rb +1 -1
- data/test/stress.rb +2 -0
- data/test/test_backend.rb +33 -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_timer.rb +1 -1
- metadata +4 -60
@@ -1,3 +1,41 @@
|
|
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
|
|
3
41
|
#include <netdb.h>
|
@@ -76,17 +114,27 @@ void break_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
|
|
76
114
|
// of a *blocking* event loop (waking it up) in a thread-safe, signal-safe manner
|
77
115
|
}
|
78
116
|
|
117
|
+
inline struct ev_loop *libev_new_loop() {
|
118
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
119
|
+
return ev_loop_new(EVFLAG_NOSIGMASK);
|
120
|
+
#else
|
121
|
+
int is_main_thread = (rb_thread_current() == rb_thread_main());
|
122
|
+
return is_main_thread ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
|
123
|
+
#endif
|
124
|
+
}
|
125
|
+
|
79
126
|
static VALUE Backend_initialize(VALUE self) {
|
80
127
|
Backend_t *backend;
|
81
|
-
|
82
|
-
int is_main_thread = (thread == rb_thread_main());
|
83
|
-
|
128
|
+
|
84
129
|
GetBackend(self, backend);
|
85
|
-
backend->ev_loop =
|
130
|
+
backend->ev_loop = libev_new_loop();
|
86
131
|
|
132
|
+
// start async watcher used for breaking a poll op (from another thread)
|
87
133
|
ev_async_init(&backend->break_async, break_async_callback);
|
88
134
|
ev_async_start(backend->ev_loop, &backend->break_async);
|
89
|
-
|
135
|
+
// the break_async watcher is unreferenced, in order for Backend_poll to not
|
136
|
+
// block when no other watcher is active
|
137
|
+
ev_unref(backend->ev_loop);
|
90
138
|
|
91
139
|
backend->currently_polling = 0;
|
92
140
|
backend->pending_count = 0;
|
@@ -672,6 +720,55 @@ error:
|
|
672
720
|
return RAISE_EXCEPTION(switchpoint_result);
|
673
721
|
}
|
674
722
|
|
723
|
+
VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
724
|
+
Backend_t *backend;
|
725
|
+
struct libev_io watcher;
|
726
|
+
rb_io_t *fptr;
|
727
|
+
VALUE switchpoint_result = Qnil;
|
728
|
+
VALUE underlying_io;
|
729
|
+
char *buf = StringValuePtr(str);
|
730
|
+
long len = RSTRING_LEN(str);
|
731
|
+
long left = len;
|
732
|
+
int flags_int = NUM2INT(flags);
|
733
|
+
|
734
|
+
underlying_io = rb_ivar_get(io, ID_ivar_io);
|
735
|
+
if (underlying_io != Qnil) io = underlying_io;
|
736
|
+
GetBackend(self, backend);
|
737
|
+
io = rb_io_get_write_io(io);
|
738
|
+
GetOpenFile(io, fptr);
|
739
|
+
io_set_nonblock(fptr, io);
|
740
|
+
watcher.fiber = Qnil;
|
741
|
+
|
742
|
+
while (left > 0) {
|
743
|
+
ssize_t n = send(fptr->fd, buf, left, flags_int);
|
744
|
+
if (n < 0) {
|
745
|
+
int e = errno;
|
746
|
+
if ((e != EWOULDBLOCK && e != EAGAIN)) rb_syserr_fail(e, strerror(e));
|
747
|
+
|
748
|
+
switchpoint_result = libev_wait_fd_with_watcher(backend, fptr->fd, &watcher, EV_WRITE);
|
749
|
+
|
750
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
751
|
+
}
|
752
|
+
else {
|
753
|
+
buf += n;
|
754
|
+
left -= n;
|
755
|
+
}
|
756
|
+
}
|
757
|
+
|
758
|
+
if (watcher.fiber == Qnil) {
|
759
|
+
switchpoint_result = backend_snooze();
|
760
|
+
|
761
|
+
if (TEST_EXCEPTION(switchpoint_result)) goto error;
|
762
|
+
}
|
763
|
+
|
764
|
+
RB_GC_GUARD(watcher.fiber);
|
765
|
+
RB_GC_GUARD(switchpoint_result);
|
766
|
+
|
767
|
+
return INT2NUM(len);
|
768
|
+
error:
|
769
|
+
return RAISE_EXCEPTION(switchpoint_result);
|
770
|
+
}
|
771
|
+
|
675
772
|
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
676
773
|
Backend_t *backend;
|
677
774
|
rb_io_t *fptr;
|
@@ -799,6 +896,7 @@ VALUE Backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
799
896
|
return result;
|
800
897
|
}
|
801
898
|
|
899
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
802
900
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
803
901
|
int pid_int = NUM2INT(pid);
|
804
902
|
int fd = pidfd_open(pid_int, 0);
|
@@ -811,18 +909,53 @@ VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
|
811
909
|
RAISE_IF_EXCEPTION(resume_value);
|
812
910
|
RB_GC_GUARD(resume_value);
|
813
911
|
}
|
912
|
+
else {
|
913
|
+
int e = errno;
|
914
|
+
rb_syserr_fail(e, strerror(e));
|
915
|
+
}
|
814
916
|
|
815
917
|
int status = 0;
|
816
918
|
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
817
919
|
if (ret < 0) {
|
818
920
|
int e = errno;
|
819
|
-
|
820
|
-
ret = pid_int;
|
821
|
-
else
|
822
|
-
rb_syserr_fail(e, strerror(e));
|
921
|
+
rb_syserr_fail(e, strerror(e));
|
823
922
|
}
|
824
923
|
return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
|
825
924
|
}
|
925
|
+
#else
|
926
|
+
struct libev_child {
|
927
|
+
struct ev_child child;
|
928
|
+
VALUE fiber;
|
929
|
+
};
|
930
|
+
|
931
|
+
void Backend_child_callback(EV_P_ ev_child *w, int revents) {
|
932
|
+
struct libev_child *watcher = (struct libev_child *)w;
|
933
|
+
int exit_status = WEXITSTATUS(w->rstatus);
|
934
|
+
VALUE status;
|
935
|
+
|
936
|
+
status = rb_ary_new_from_args(2, INT2NUM(w->rpid), INT2NUM(exit_status));
|
937
|
+
Fiber_make_runnable(watcher->fiber, status);
|
938
|
+
}
|
939
|
+
|
940
|
+
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
941
|
+
Backend_t *backend;
|
942
|
+
struct libev_child watcher;
|
943
|
+
VALUE switchpoint_result = Qnil;
|
944
|
+
GetBackend(self, backend);
|
945
|
+
|
946
|
+
watcher.fiber = rb_fiber_current();
|
947
|
+
ev_child_init(&watcher.child, Backend_child_callback, NUM2INT(pid), 0);
|
948
|
+
ev_child_start(backend->ev_loop, &watcher.child);
|
949
|
+
|
950
|
+
switchpoint_result = backend_await(backend);
|
951
|
+
|
952
|
+
ev_child_stop(backend->ev_loop, &watcher.child);
|
953
|
+
RAISE_IF_EXCEPTION(switchpoint_result);
|
954
|
+
RB_GC_GUARD(watcher.fiber);
|
955
|
+
RB_GC_GUARD(switchpoint_result);
|
956
|
+
return switchpoint_result;
|
957
|
+
}
|
958
|
+
#endif
|
826
959
|
|
827
960
|
void Backend_async_callback(EV_P_ ev_async *w, int revents) { }
|
828
961
|
|
@@ -851,7 +984,7 @@ VALUE Backend_kind(VALUE self) {
|
|
851
984
|
void Init_Backend() {
|
852
985
|
ev_set_allocator(xrealloc);
|
853
986
|
|
854
|
-
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend",
|
987
|
+
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
855
988
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
856
989
|
|
857
990
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
@@ -871,7 +1004,8 @@ void Init_Backend() {
|
|
871
1004
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
872
1005
|
rb_define_method(cBackend, "recv_loop", Backend_read_loop, 1);
|
873
1006
|
rb_define_method(cBackend, "recv_feed_loop", Backend_feed_loop, 3);
|
874
|
-
rb_define_method(cBackend, "send",
|
1007
|
+
rb_define_method(cBackend, "send", Backend_send, 3);
|
1008
|
+
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
875
1009
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
876
1010
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
877
1011
|
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
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,15 +4,19 @@ 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
|
8
9
|
|
9
|
-
if
|
10
|
+
if RUBY_PLATFORM =~ /linux/ && `uname -sr` =~ /Linux 5\.([\d+])/
|
10
11
|
kernel_minor_version = $1.gsub('.', '').to_i
|
11
|
-
use_liburing = kernel_minor_version >= 6
|
12
|
+
use_liburing = !force_use_libev && kernel_minor_version >= 6
|
13
|
+
use_pidfd_open = kernel_minor_version >= 3
|
12
14
|
end
|
13
15
|
|
16
|
+
$defs << '-DPOLYPHONY_USE_PIDFD_OPEN' if use_pidfd_open
|
14
17
|
if use_liburing
|
15
18
|
$defs << "-DPOLYPHONY_BACKEND_LIBURING"
|
19
|
+
$defs << "-DPOLYPHONY_UNSET_NONBLOCK" if RUBY_VERSION =~ /^3/
|
16
20
|
$CFLAGS << " -Wno-pointer-arith"
|
17
21
|
else
|
18
22
|
$defs << "-DPOLYPHONY_BACKEND_LIBEV"
|
@@ -23,6 +27,7 @@ else
|
|
23
27
|
$defs << '-DEV_USE_KQUEUE' if have_header('sys/event.h') && have_header('sys/queue.h')
|
24
28
|
$defs << '-DEV_USE_PORT' if have_type('port_event_t', 'port.h')
|
25
29
|
$defs << '-DHAVE_SYS_RESOURCE_H' if have_header('sys/resource.h')
|
30
|
+
|
26
31
|
$CFLAGS << " -Wno-comment"
|
27
32
|
$CFLAGS << " -Wno-unused-result"
|
28
33
|
$CFLAGS << " -Wno-dangling-else"
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -46,11 +46,105 @@ 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
|
+
VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
52
|
+
return Backend_accept(BACKEND(), server_socket, socket_class);
|
53
|
+
}
|
54
|
+
|
55
|
+
VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
56
|
+
return Backend_accept_loop(BACKEND(), server_socket, socket_class);
|
57
|
+
}
|
58
|
+
|
59
|
+
VALUE Polyphony_backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port) {
|
60
|
+
return Backend_connect(BACKEND(), io, addr, port);
|
61
|
+
}
|
62
|
+
|
63
|
+
VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
64
|
+
return Backend_feed_loop(BACKEND(), io, receiver, method);
|
65
|
+
}
|
66
|
+
|
67
|
+
VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
|
68
|
+
return Backend_read(BACKEND(), io, str, length, to_eof);
|
69
|
+
}
|
70
|
+
|
71
|
+
VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
|
72
|
+
return Backend_read_loop(BACKEND(), io);
|
73
|
+
}
|
74
|
+
|
75
|
+
VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
76
|
+
return Backend_recv(BACKEND(), io, str, length);
|
77
|
+
}
|
78
|
+
|
79
|
+
VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
|
80
|
+
return Backend_recv_loop(BACKEND(), io);
|
81
|
+
}
|
82
|
+
|
83
|
+
VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
84
|
+
return Backend_recv_feed_loop(BACKEND(), io, receiver, method);
|
85
|
+
}
|
86
|
+
|
87
|
+
VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
|
88
|
+
return Backend_send(BACKEND(), io, msg, flags);
|
89
|
+
}
|
90
|
+
|
91
|
+
VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
|
92
|
+
return Backend_sendv(BACKEND(), io, ary, flags);
|
93
|
+
}
|
94
|
+
|
95
|
+
VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
|
96
|
+
return Backend_sleep(BACKEND(), duration);
|
97
|
+
}
|
98
|
+
|
99
|
+
VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
|
100
|
+
return Backend_timeout(argc, argv, BACKEND());
|
101
|
+
}
|
102
|
+
|
103
|
+
VALUE Polyphony_backend_timer_loop(VALUE self, VALUE interval) {
|
104
|
+
return Backend_timer_loop(BACKEND(), interval);
|
105
|
+
}
|
106
|
+
|
107
|
+
VALUE Polyphony_backend_wait_event(VALUE self, VALUE raise) {
|
108
|
+
return Backend_wait_event(BACKEND(), raise);
|
109
|
+
}
|
110
|
+
|
111
|
+
VALUE Polyphony_backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
112
|
+
return Backend_wait_io(BACKEND(), io, write);
|
113
|
+
}
|
114
|
+
|
115
|
+
VALUE Polyphony_backend_waitpid(VALUE self, VALUE pid) {
|
116
|
+
return Backend_waitpid(BACKEND(), pid);
|
117
|
+
}
|
118
|
+
|
119
|
+
VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
|
120
|
+
return Backend_write_m(argc, argv, BACKEND());
|
121
|
+
}
|
122
|
+
|
49
123
|
void Init_Polyphony() {
|
50
124
|
mPolyphony = rb_define_module("Polyphony");
|
51
125
|
|
52
126
|
rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
|
53
127
|
|
128
|
+
// backend methods
|
129
|
+
rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
|
130
|
+
rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
|
131
|
+
rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
|
132
|
+
rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
|
133
|
+
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 4);
|
134
|
+
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
|
135
|
+
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
|
136
|
+
rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
|
137
|
+
rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
|
138
|
+
rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
|
139
|
+
rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
|
140
|
+
rb_define_singleton_method(mPolyphony, "backend_sleep", Polyphony_backend_sleep, 1);
|
141
|
+
rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
|
142
|
+
rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
|
143
|
+
rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
|
144
|
+
rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
|
145
|
+
rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
|
146
|
+
rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
|
147
|
+
|
54
148
|
rb_define_global_function("snooze", Polyphony_snooze, 0);
|
55
149
|
rb_define_global_function("suspend", Polyphony_suspend, 0);
|
56
150
|
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -23,9 +23,9 @@
|
|
23
23
|
#define COND_TRACE(...) if (__tracing_enabled__) { TRACE(__VA_ARGS__); }
|
24
24
|
|
25
25
|
// exceptions
|
26
|
-
#define TEST_EXCEPTION(ret) (
|
26
|
+
#define TEST_EXCEPTION(ret) (rb_obj_is_kind_of(ret, rb_eException) == Qtrue)
|
27
27
|
#define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
|
28
|
-
#define RAISE_IF_EXCEPTION(ret) if (
|
28
|
+
#define RAISE_IF_EXCEPTION(ret) if (rb_obj_is_kind_of(ret, rb_eException) == Qtrue) { RAISE_EXCEPTION(ret); }
|
29
29
|
#define RAISE_IF_NOT_NIL(ret) if (ret != Qnil) { RAISE_EXCEPTION(ret); }
|
30
30
|
|
31
31
|
// Fiber#transfer
|
@@ -89,6 +89,32 @@ void Runqueue_clear(VALUE self);
|
|
89
89
|
long Runqueue_len(VALUE self);
|
90
90
|
int Runqueue_empty_p(VALUE self);
|
91
91
|
|
92
|
+
#ifdef POLYPHONY_BACKEND_LIBEV
|
93
|
+
#define Backend_recv_loop Backend_read_loop
|
94
|
+
#define Backend_recv_feed_loop Backend_feed_loop
|
95
|
+
#endif
|
96
|
+
|
97
|
+
// Backend public interface
|
98
|
+
|
99
|
+
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
|
100
|
+
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
|
101
|
+
VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
|
102
|
+
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
103
|
+
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
|
104
|
+
VALUE Backend_read_loop(VALUE self, VALUE io);
|
105
|
+
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length);
|
106
|
+
VALUE Backend_recv_loop(VALUE self, VALUE io);
|
107
|
+
VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
108
|
+
VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
|
109
|
+
VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
|
110
|
+
VALUE Backend_sleep(VALUE self, VALUE duration);
|
111
|
+
VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
|
112
|
+
VALUE Backend_timer_loop(VALUE self, VALUE interval);
|
113
|
+
VALUE Backend_wait_event(VALUE self, VALUE raise);
|
114
|
+
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
|
115
|
+
VALUE Backend_waitpid(VALUE self, VALUE pid);
|
116
|
+
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
|
117
|
+
|
92
118
|
unsigned int Backend_pending_count(VALUE self);
|
93
119
|
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
|
94
120
|
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
data/ext/polyphony/queue.c
CHANGED
@@ -247,7 +247,7 @@ VALUE Queue_size_m(VALUE self) {
|
|
247
247
|
}
|
248
248
|
|
249
249
|
void Init_Queue() {
|
250
|
-
cQueue = rb_define_class_under(mPolyphony, "Queue",
|
250
|
+
cQueue = rb_define_class_under(mPolyphony, "Queue", rb_cObject);
|
251
251
|
rb_define_alloc_func(cQueue, Queue_allocate);
|
252
252
|
|
253
253
|
rb_define_method(cQueue, "initialize", Queue_initialize, -1);
|
data/ext/polyphony/runqueue.c
CHANGED
@@ -101,7 +101,7 @@ int Runqueue_empty_p(VALUE self) {
|
|
101
101
|
}
|
102
102
|
|
103
103
|
void Init_Runqueue() {
|
104
|
-
cRunqueue = rb_define_class_under(mPolyphony, "Runqueue",
|
104
|
+
cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cObject);
|
105
105
|
rb_define_alloc_func(cRunqueue, Runqueue_allocate);
|
106
106
|
|
107
107
|
rb_define_method(cRunqueue, "initialize", Runqueue_initialize, 0);
|
@@ -15,8 +15,8 @@ module ::PG
|
|
15
15
|
res = conn.connect_poll
|
16
16
|
case res
|
17
17
|
when PGRES_POLLING_FAILED then raise Error, conn.error_message
|
18
|
-
when PGRES_POLLING_READING then
|
19
|
-
when PGRES_POLLING_WRITING then
|
18
|
+
when PGRES_POLLING_READING then Polyphony.backend_wait_io(socket_io, false)
|
19
|
+
when PGRES_POLLING_WRITING then Polyphony.backend_wait_io(socket_io, true)
|
20
20
|
when PGRES_POLLING_OK then return conn.setnonblocking(true)
|
21
21
|
end
|
22
22
|
end
|
@@ -42,7 +42,7 @@ class ::PG::Connection
|
|
42
42
|
|
43
43
|
def get_result(&block)
|
44
44
|
while is_busy
|
45
|
-
|
45
|
+
Polyphony.backend_wait_io(socket_io, false)
|
46
46
|
consume_input
|
47
47
|
end
|
48
48
|
orig_get_result(&block)
|
@@ -59,7 +59,7 @@ class ::PG::Connection
|
|
59
59
|
|
60
60
|
def block(_timeout = 0)
|
61
61
|
while is_busy
|
62
|
-
|
62
|
+
Polyphony.backend_wait_io(socket_io, false)
|
63
63
|
consume_input
|
64
64
|
end
|
65
65
|
end
|
@@ -97,7 +97,7 @@ class ::PG::Connection
|
|
97
97
|
return move_on_after(timeout) { wait_for_notify(&block) } if timeout
|
98
98
|
|
99
99
|
while true
|
100
|
-
|
100
|
+
Polyphony.backend_wait_io(socket_io, false)
|
101
101
|
consume_input
|
102
102
|
notice = notifies
|
103
103
|
next unless notice
|