polyphony 0.49.2 → 0.53.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 +34 -0
- data/Gemfile.lock +7 -68
- data/TODO.md +37 -3
- data/examples/core/forking.rb +2 -2
- data/examples/core/nested.rb +21 -0
- data/examples/core/suspend.rb +13 -0
- data/examples/core/terminate_main_fiber.rb +12 -0
- data/examples/io/echo_server.rb +1 -0
- data/examples/io/tcp_proxy.rb +2 -2
- data/ext/polyphony/backend_common.h +58 -8
- data/ext/polyphony/backend_io_uring.c +223 -41
- 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 +322 -34
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/extconf.rb +9 -2
- data/ext/polyphony/fiber.c +2 -1
- data/ext/polyphony/polyphony.c +102 -0
- data/ext/polyphony/polyphony.h +33 -2
- data/ext/polyphony/polyphony_ext.c +3 -0
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +7 -1
- data/ext/polyphony/runqueue_ring_buffer.c +9 -0
- data/ext/polyphony/runqueue_ring_buffer.h +1 -0
- data/ext/polyphony/socket_extensions.c +33 -0
- data/ext/polyphony/thread.c +14 -0
- 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/exceptions.rb +1 -0
- data/lib/polyphony/core/global_api.rb +6 -6
- data/lib/polyphony/core/sync.rb +1 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +63 -20
- data/lib/polyphony/extensions/core.rb +5 -5
- data/lib/polyphony/extensions/fiber.rb +2 -0
- 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 +69 -5
- data/test/test_fiber.rb +16 -0
- 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_timer.rb +41 -8
- metadata +22 -60
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"
|
data/ext/polyphony/fiber.c
CHANGED
|
@@ -101,7 +101,8 @@ VALUE Fiber_await(VALUE self) {
|
|
|
101
101
|
}
|
|
102
102
|
rb_hash_aset(waiting_fibers, fiber, Qtrue);
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
VALUE backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
|
|
105
|
+
result = Backend_wait_event(backend, Qnil);
|
|
105
106
|
|
|
106
107
|
rb_hash_delete(waiting_fibers, fiber);
|
|
107
108
|
RAISE_IF_EXCEPTION(result);
|
data/ext/polyphony/polyphony.c
CHANGED
|
@@ -46,11 +46,113 @@ VALUE Polyphony_trace(VALUE self, VALUE enabled) {
|
|
|
46
46
|
return Qnil;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
50
|
+
return Backend_accept(BACKEND(), server_socket, socket_class);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
54
|
+
return Backend_accept_loop(BACKEND(), server_socket, socket_class);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
VALUE Polyphony_backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port) {
|
|
58
|
+
return Backend_connect(BACKEND(), io, addr, port);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
62
|
+
return Backend_feed_loop(BACKEND(), io, receiver, method);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
|
|
66
|
+
return Backend_read(BACKEND(), io, str, length, to_eof);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
|
|
70
|
+
return Backend_read_loop(BACKEND(), io);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
74
|
+
return Backend_recv(BACKEND(), io, str, length);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
|
|
78
|
+
return Backend_recv_loop(BACKEND(), io);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
82
|
+
return Backend_recv_feed_loop(BACKEND(), io, receiver, method);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
VALUE Polyphony_backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags) {
|
|
86
|
+
return Backend_send(BACKEND(), io, msg, flags);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
VALUE Polyphony_backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
|
|
90
|
+
return Backend_sendv(BACKEND(), io, ary, flags);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
|
|
94
|
+
return Backend_sleep(BACKEND(), duration);
|
|
95
|
+
}
|
|
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
|
+
|
|
105
|
+
VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
|
|
106
|
+
return Backend_timeout(argc, argv, BACKEND());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
VALUE Polyphony_backend_timer_loop(VALUE self, VALUE interval) {
|
|
110
|
+
return Backend_timer_loop(BACKEND(), interval);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
VALUE Polyphony_backend_wait_event(VALUE self, VALUE raise) {
|
|
114
|
+
return Backend_wait_event(BACKEND(), raise);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
VALUE Polyphony_backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
118
|
+
return Backend_wait_io(BACKEND(), io, write);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
VALUE Polyphony_backend_waitpid(VALUE self, VALUE pid) {
|
|
122
|
+
return Backend_waitpid(BACKEND(), pid);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
|
|
126
|
+
return Backend_write_m(argc, argv, BACKEND());
|
|
127
|
+
}
|
|
128
|
+
|
|
49
129
|
void Init_Polyphony() {
|
|
50
130
|
mPolyphony = rb_define_module("Polyphony");
|
|
51
131
|
|
|
52
132
|
rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
|
|
53
133
|
|
|
134
|
+
// backend methods
|
|
135
|
+
rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
|
|
136
|
+
rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
|
|
137
|
+
rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
|
|
138
|
+
rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
|
|
139
|
+
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 4);
|
|
140
|
+
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
|
|
141
|
+
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
|
|
142
|
+
rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
|
|
143
|
+
rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
|
|
144
|
+
rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
|
|
145
|
+
rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
|
|
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);
|
|
149
|
+
rb_define_singleton_method(mPolyphony, "backend_timeout", Polyphony_backend_timeout, -1);
|
|
150
|
+
rb_define_singleton_method(mPolyphony, "backend_timer_loop", Polyphony_backend_timer_loop, 1);
|
|
151
|
+
rb_define_singleton_method(mPolyphony, "backend_wait_event", Polyphony_backend_wait_event, 1);
|
|
152
|
+
rb_define_singleton_method(mPolyphony, "backend_wait_io", Polyphony_backend_wait_io, 2);
|
|
153
|
+
rb_define_singleton_method(mPolyphony, "backend_waitpid", Polyphony_backend_waitpid, 1);
|
|
154
|
+
rb_define_singleton_method(mPolyphony, "backend_write", Polyphony_backend_write, -1);
|
|
155
|
+
|
|
54
156
|
rb_define_global_function("snooze", Polyphony_snooze, 0);
|
|
55
157
|
rb_define_global_function("suspend", Polyphony_suspend, 0);
|
|
56
158
|
|
data/ext/polyphony/polyphony.h
CHANGED
|
@@ -23,14 +23,16 @@
|
|
|
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
|
|
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;
|
|
@@ -84,10 +86,39 @@ void Runqueue_push(VALUE self, VALUE fiber, VALUE value, int reschedule);
|
|
|
84
86
|
void Runqueue_unshift(VALUE self, VALUE fiber, VALUE value, int reschedule);
|
|
85
87
|
runqueue_entry Runqueue_shift(VALUE self);
|
|
86
88
|
void Runqueue_delete(VALUE self, VALUE fiber);
|
|
89
|
+
int Runqueue_index_of(VALUE self, VALUE fiber);
|
|
87
90
|
void Runqueue_clear(VALUE self);
|
|
88
91
|
long Runqueue_len(VALUE self);
|
|
89
92
|
int Runqueue_empty_p(VALUE self);
|
|
90
93
|
|
|
94
|
+
#ifdef POLYPHONY_BACKEND_LIBEV
|
|
95
|
+
#define Backend_recv_loop Backend_read_loop
|
|
96
|
+
#define Backend_recv_feed_loop Backend_feed_loop
|
|
97
|
+
#endif
|
|
98
|
+
|
|
99
|
+
// Backend public interface
|
|
100
|
+
|
|
101
|
+
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
102
|
+
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
103
|
+
VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
|
|
104
|
+
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
|
105
|
+
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
|
|
106
|
+
VALUE Backend_read_loop(VALUE self, VALUE io);
|
|
107
|
+
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length);
|
|
108
|
+
VALUE Backend_recv_loop(VALUE self, VALUE io);
|
|
109
|
+
VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
|
110
|
+
VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
|
|
111
|
+
VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
|
|
112
|
+
VALUE Backend_sleep(VALUE self, VALUE duration);
|
|
113
|
+
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen);
|
|
114
|
+
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize);
|
|
115
|
+
VALUE Backend_timeout(int argc,VALUE *argv, VALUE self);
|
|
116
|
+
VALUE Backend_timer_loop(VALUE self, VALUE interval);
|
|
117
|
+
VALUE Backend_wait_event(VALUE self, VALUE raise);
|
|
118
|
+
VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
|
|
119
|
+
VALUE Backend_waitpid(VALUE self, VALUE pid);
|
|
120
|
+
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
|
|
121
|
+
|
|
91
122
|
unsigned int Backend_pending_count(VALUE self);
|
|
92
123
|
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
|
|
93
124
|
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
|
@@ -6,6 +6,7 @@ void Init_Backend();
|
|
|
6
6
|
void Init_Queue();
|
|
7
7
|
void Init_Event();
|
|
8
8
|
void Init_Runqueue();
|
|
9
|
+
void Init_SocketExtensions();
|
|
9
10
|
void Init_Thread();
|
|
10
11
|
void Init_Tracing();
|
|
11
12
|
|
|
@@ -24,6 +25,8 @@ void Init_polyphony_ext() {
|
|
|
24
25
|
Init_Thread();
|
|
25
26
|
Init_Tracing();
|
|
26
27
|
|
|
28
|
+
Init_SocketExtensions();
|
|
29
|
+
|
|
27
30
|
#ifdef POLYPHONY_PLAYGROUND
|
|
28
31
|
playground();
|
|
29
32
|
#endif
|
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
|
@@ -74,6 +74,12 @@ void Runqueue_delete(VALUE self, VALUE fiber) {
|
|
|
74
74
|
runqueue_ring_buffer_delete(&runqueue->entries, fiber);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
int Runqueue_index_of(VALUE self, VALUE fiber) {
|
|
78
|
+
Runqueue_t *runqueue;
|
|
79
|
+
GetRunqueue(self, runqueue);
|
|
80
|
+
return runqueue_ring_buffer_index_of(&runqueue->entries, fiber);
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
void Runqueue_clear(VALUE self) {
|
|
78
84
|
Runqueue_t *runqueue;
|
|
79
85
|
GetRunqueue(self, runqueue);
|
|
@@ -95,7 +101,7 @@ int Runqueue_empty_p(VALUE self) {
|
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
void Init_Runqueue() {
|
|
98
|
-
cRunqueue = rb_define_class_under(mPolyphony, "Runqueue",
|
|
104
|
+
cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cObject);
|
|
99
105
|
rb_define_alloc_func(cRunqueue, Runqueue_allocate);
|
|
100
106
|
|
|
101
107
|
rb_define_method(cRunqueue, "initialize", Runqueue_initialize, 0);
|
|
@@ -80,6 +80,15 @@ void runqueue_ring_buffer_delete(runqueue_ring_buffer *buffer, VALUE fiber) {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
int runqueue_ring_buffer_index_of(runqueue_ring_buffer *buffer, VALUE fiber) {
|
|
84
|
+
for (unsigned int i = 0; i < buffer->count; i++) {
|
|
85
|
+
unsigned int idx = (buffer->head + i) % buffer->size;
|
|
86
|
+
if (buffer->entries[idx].fiber == fiber)
|
|
87
|
+
return i;
|
|
88
|
+
}
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
void runqueue_ring_buffer_clear(runqueue_ring_buffer *buffer) {
|
|
84
93
|
buffer->count = buffer->head = buffer->tail = 0;
|
|
85
94
|
}
|
|
@@ -27,5 +27,6 @@ void runqueue_ring_buffer_unshift(runqueue_ring_buffer *buffer, VALUE fiber, VAL
|
|
|
27
27
|
void runqueue_ring_buffer_push(runqueue_ring_buffer *buffer, VALUE fiber, VALUE value);
|
|
28
28
|
|
|
29
29
|
void runqueue_ring_buffer_delete(runqueue_ring_buffer *buffer, VALUE fiber);
|
|
30
|
+
int runqueue_ring_buffer_index_of(runqueue_ring_buffer *buffer, VALUE fiber);
|
|
30
31
|
|
|
31
32
|
#endif /* RUNQUEUE_RING_BUFFER_H */
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#include "polyphony.h"
|
|
2
|
+
|
|
3
|
+
VALUE Socket_send(VALUE self, VALUE msg, VALUE flags) {
|
|
4
|
+
return Backend_send(BACKEND(), self, msg, flags);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
VALUE Socket_write(int argc, VALUE *argv, VALUE self) {
|
|
8
|
+
VALUE ary = rb_ary_new_from_values(argc, argv);
|
|
9
|
+
VALUE result = Backend_sendv(BACKEND(), self, ary, INT2NUM(0));
|
|
10
|
+
RB_GC_GUARD(ary);
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
VALUE Socket_double_chevron(VALUE self, VALUE msg) {
|
|
15
|
+
Backend_send(BACKEND(), self, msg, INT2NUM(0));
|
|
16
|
+
return self;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void Init_SocketExtensions() {
|
|
20
|
+
rb_require("socket");
|
|
21
|
+
|
|
22
|
+
VALUE cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
|
|
23
|
+
VALUE cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
|
24
|
+
|
|
25
|
+
rb_define_method(cSocket, "send", Socket_send, 2);
|
|
26
|
+
rb_define_method(cTCPSocket, "send", Socket_send, 2);
|
|
27
|
+
|
|
28
|
+
rb_define_method(cSocket, "write", Socket_write, -1);
|
|
29
|
+
rb_define_method(cTCPSocket, "write", Socket_write, -1);
|
|
30
|
+
|
|
31
|
+
rb_define_method(cSocket, "<<", Socket_double_chevron, 1);
|
|
32
|
+
rb_define_method(cTCPSocket, "<<", Socket_double_chevron, 1);
|
|
33
|
+
}
|
data/ext/polyphony/thread.c
CHANGED
|
@@ -59,6 +59,18 @@ void schedule_fiber(VALUE self, VALUE fiber, VALUE value, int prioritize) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
VALUE Thread_fiber_scheduling_index(VALUE self, VALUE fiber) {
|
|
63
|
+
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
|
64
|
+
|
|
65
|
+
return INT2NUM(Runqueue_index_of(runqueue, fiber));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
VALUE Thread_fiber_unschedule(VALUE self, VALUE fiber) {
|
|
69
|
+
VALUE runqueue = rb_ivar_get(self, ID_ivar_runqueue);
|
|
70
|
+
Runqueue_delete(runqueue, fiber);
|
|
71
|
+
return self;
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
|
63
75
|
schedule_fiber(self, fiber, value, 0);
|
|
64
76
|
return self;
|
|
@@ -135,6 +147,8 @@ void Init_Thread() {
|
|
|
135
147
|
rb_define_method(rb_cThread, "schedule_fiber_with_priority",
|
|
136
148
|
Thread_schedule_fiber_with_priority, 2);
|
|
137
149
|
rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
|
|
150
|
+
rb_define_method(rb_cThread, "fiber_scheduling_index", Thread_fiber_scheduling_index, 1);
|
|
151
|
+
rb_define_method(rb_cThread, "fiber_unschedule", Thread_fiber_unschedule, 1);
|
|
138
152
|
|
|
139
153
|
rb_define_method(rb_cThread, "debug!", Thread_debug, 0);
|
|
140
154
|
|
|
@@ -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
|
|
@@ -7,7 +7,7 @@ module Polyphony
|
|
|
7
7
|
def watch(cmd = nil, &block)
|
|
8
8
|
terminated = nil
|
|
9
9
|
pid = cmd ? Kernel.spawn(cmd) : Polyphony.fork(&block)
|
|
10
|
-
|
|
10
|
+
Polyphony.backend_waitpid(pid)
|
|
11
11
|
terminated = true
|
|
12
12
|
ensure
|
|
13
13
|
kill_process(pid) unless terminated || pid.nil?
|
|
@@ -23,9 +23,9 @@ module Polyphony
|
|
|
23
23
|
|
|
24
24
|
def kill_and_await(sig, pid)
|
|
25
25
|
::Process.kill(sig, pid)
|
|
26
|
-
|
|
27
|
-
rescue Errno::
|
|
28
|
-
#
|
|
26
|
+
Polyphony.backend_waitpid(pid)
|
|
27
|
+
rescue Errno::ESRCH
|
|
28
|
+
# process doesn't exist
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|