polyphony 0.58 → 0.61
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/CHANGELOG.md +26 -0
- data/Gemfile.lock +15 -29
- data/examples/core/message_based_supervision.rb +51 -0
- data/examples/io/echo_server.rb +16 -7
- data/ext/polyphony/backend_common.c +160 -7
- data/ext/polyphony/backend_common.h +34 -2
- data/ext/polyphony/backend_io_uring.c +119 -40
- data/ext/polyphony/backend_io_uring_context.c +10 -1
- data/ext/polyphony/backend_io_uring_context.h +5 -3
- data/ext/polyphony/backend_libev.c +109 -31
- data/ext/polyphony/extconf.rb +2 -2
- data/ext/polyphony/fiber.c +1 -34
- data/ext/polyphony/polyphony.c +12 -19
- data/ext/polyphony/polyphony.h +9 -20
- data/ext/polyphony/polyphony_ext.c +0 -4
- data/ext/polyphony/queue.c +12 -12
- data/ext/polyphony/runqueue.c +21 -98
- data/ext/polyphony/runqueue.h +26 -0
- data/ext/polyphony/thread.c +6 -113
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/fiber.rb +102 -82
- data/lib/polyphony/extensions/io.rb +10 -9
- data/lib/polyphony/extensions/openssl.rb +14 -4
- data/lib/polyphony/extensions/socket.rb +15 -15
- data/lib/polyphony/extensions/thread.rb +1 -1
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +0 -7
- data/test/test_backend.rb +46 -9
- data/test/test_ext.rb +1 -1
- data/test/test_fiber.rb +106 -18
- data/test/test_global_api.rb +1 -1
- data/test/test_io.rb +29 -0
- data/test/test_supervise.rb +100 -100
- data/test/test_thread.rb +5 -11
- data/test/test_thread_pool.rb +1 -1
- data/test/test_trace.rb +28 -49
- metadata +5 -109
- data/ext/polyphony/tracing.c +0 -11
- data/lib/polyphony/adapters/trace.rb +0 -138
data/ext/polyphony/extconf.rb
CHANGED
|
@@ -8,8 +8,8 @@ use_pidfd_open = false
|
|
|
8
8
|
force_use_libev = ENV['POLYPHONY_USE_LIBEV'] != nil
|
|
9
9
|
linux = RUBY_PLATFORM =~ /linux/
|
|
10
10
|
|
|
11
|
-
if linux && `uname -sr` =~ /Linux 5\.(
|
|
12
|
-
kernel_minor_version = $1.
|
|
11
|
+
if linux && `uname -sr` =~ /Linux 5\.(\d+)/
|
|
12
|
+
kernel_minor_version = $1.to_i
|
|
13
13
|
use_liburing = !force_use_libev && kernel_minor_version >= 6
|
|
14
14
|
use_pidfd_open = kernel_minor_version >= 3
|
|
15
15
|
end
|
data/ext/polyphony/fiber.c
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#include "polyphony.h"
|
|
2
2
|
|
|
3
|
-
ID ID_fiber_trace;
|
|
4
3
|
ID ID_ivar_auto_watcher;
|
|
5
4
|
ID ID_ivar_mailbox;
|
|
6
5
|
ID ID_ivar_result;
|
|
@@ -82,34 +81,6 @@ static VALUE Fiber_state(VALUE self) {
|
|
|
82
81
|
return SYM_waiting;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
VALUE Fiber_await(VALUE self) {
|
|
86
|
-
VALUE result;
|
|
87
|
-
|
|
88
|
-
// we compare with false, since a fiber that has not yet started will have
|
|
89
|
-
// @running set to nil
|
|
90
|
-
if (rb_ivar_get(self, ID_ivar_running) == Qfalse) {
|
|
91
|
-
result = rb_ivar_get(self, ID_ivar_result);
|
|
92
|
-
RAISE_IF_EXCEPTION(result);
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
VALUE fiber = rb_fiber_current();
|
|
97
|
-
VALUE waiting_fibers = rb_ivar_get(self, ID_ivar_waiting_fibers);
|
|
98
|
-
if (waiting_fibers == Qnil) {
|
|
99
|
-
waiting_fibers = rb_hash_new();
|
|
100
|
-
rb_ivar_set(self, ID_ivar_waiting_fibers, waiting_fibers);
|
|
101
|
-
}
|
|
102
|
-
rb_hash_aset(waiting_fibers, fiber, Qtrue);
|
|
103
|
-
|
|
104
|
-
VALUE backend = rb_ivar_get(rb_thread_current(), ID_ivar_backend);
|
|
105
|
-
result = Backend_wait_event(backend, Qnil);
|
|
106
|
-
|
|
107
|
-
rb_hash_delete(waiting_fibers, fiber);
|
|
108
|
-
RAISE_IF_EXCEPTION(result);
|
|
109
|
-
RB_GC_GUARD(result);
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
84
|
VALUE Fiber_send(VALUE self, VALUE value) {
|
|
114
85
|
VALUE mailbox = rb_ivar_get(self, ID_ivar_mailbox);
|
|
115
86
|
if (mailbox == Qnil) {
|
|
@@ -126,7 +97,7 @@ VALUE Fiber_receive(VALUE self) {
|
|
|
126
97
|
mailbox = rb_funcall(cQueue, ID_new, 0);
|
|
127
98
|
rb_ivar_set(self, ID_ivar_mailbox, mailbox);
|
|
128
99
|
}
|
|
129
|
-
return Queue_shift(mailbox);
|
|
100
|
+
return Queue_shift(mailbox);
|
|
130
101
|
}
|
|
131
102
|
|
|
132
103
|
VALUE Fiber_mailbox(VALUE self) {
|
|
@@ -151,9 +122,6 @@ void Init_Fiber() {
|
|
|
151
122
|
rb_define_method(cFiber, "state", Fiber_state, 0);
|
|
152
123
|
rb_define_method(cFiber, "auto_watcher", Fiber_auto_watcher, 0);
|
|
153
124
|
|
|
154
|
-
rb_define_method(cFiber, "await", Fiber_await, 0);
|
|
155
|
-
rb_define_method(cFiber, "join", Fiber_await, 0);
|
|
156
|
-
|
|
157
125
|
rb_define_method(cFiber, "<<", Fiber_send, 1);
|
|
158
126
|
rb_define_method(cFiber, "send", Fiber_send, 1);
|
|
159
127
|
rb_define_method(cFiber, "receive", Fiber_receive, 0);
|
|
@@ -169,7 +137,6 @@ void Init_Fiber() {
|
|
|
169
137
|
rb_global_variable(&SYM_runnable);
|
|
170
138
|
rb_global_variable(&SYM_waiting);
|
|
171
139
|
|
|
172
|
-
ID_fiber_trace = rb_intern("__fiber_trace__");
|
|
173
140
|
ID_ivar_auto_watcher = rb_intern("@auto_watcher");
|
|
174
141
|
ID_ivar_mailbox = rb_intern("@mailbox");
|
|
175
142
|
ID_ivar_result = rb_intern("@result");
|
data/ext/polyphony/polyphony.c
CHANGED
|
@@ -42,11 +42,6 @@ static VALUE Polyphony_suspend(VALUE self) {
|
|
|
42
42
|
return ret;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
VALUE Polyphony_trace(VALUE self, VALUE enabled) {
|
|
46
|
-
__tracing_enabled__ = RTEST(enabled) ? 1 : 0;
|
|
47
|
-
return Qnil;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
45
|
VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
51
46
|
return Backend_accept(BACKEND(), server_socket, socket_class);
|
|
52
47
|
}
|
|
@@ -63,20 +58,20 @@ VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE me
|
|
|
63
58
|
return Backend_feed_loop(BACKEND(), io, receiver, method);
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof) {
|
|
67
|
-
return Backend_read(BACKEND(), io, str, length, to_eof);
|
|
61
|
+
VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos) {
|
|
62
|
+
return Backend_read(BACKEND(), io, str, length, to_eof, pos);
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
VALUE Polyphony_backend_read_loop(VALUE self, VALUE io) {
|
|
71
|
-
return Backend_read_loop(BACKEND(), io);
|
|
65
|
+
VALUE Polyphony_backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
66
|
+
return Backend_read_loop(BACKEND(), io, maxlen);
|
|
72
67
|
}
|
|
73
68
|
|
|
74
|
-
VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
75
|
-
return Backend_recv(BACKEND(), io, str, length);
|
|
69
|
+
VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos) {
|
|
70
|
+
return Backend_recv(BACKEND(), io, str, length, pos);
|
|
76
71
|
}
|
|
77
72
|
|
|
78
|
-
VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io) {
|
|
79
|
-
return Backend_recv_loop(BACKEND(), io);
|
|
73
|
+
VALUE Polyphony_backend_recv_loop(VALUE self, VALUE io, VALUE maxlen) {
|
|
74
|
+
return Backend_recv_loop(BACKEND(), io, maxlen);
|
|
80
75
|
}
|
|
81
76
|
|
|
82
77
|
VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
|
@@ -130,17 +125,15 @@ VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
|
|
|
130
125
|
void Init_Polyphony() {
|
|
131
126
|
mPolyphony = rb_define_module("Polyphony");
|
|
132
127
|
|
|
133
|
-
rb_define_singleton_method(mPolyphony, "trace", Polyphony_trace, 1);
|
|
134
|
-
|
|
135
128
|
// backend methods
|
|
136
129
|
rb_define_singleton_method(mPolyphony, "backend_accept", Polyphony_backend_accept, 2);
|
|
137
130
|
rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
|
|
138
131
|
rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
|
|
139
132
|
rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
|
|
140
|
-
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read,
|
|
141
|
-
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop,
|
|
142
|
-
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv,
|
|
143
|
-
rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop,
|
|
133
|
+
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
|
|
134
|
+
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
|
|
135
|
+
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
|
|
136
|
+
rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 2);
|
|
144
137
|
rb_define_singleton_method(mPolyphony, "backend_recv_feed_loop", Polyphony_backend_recv_feed_loop, 3);
|
|
145
138
|
rb_define_singleton_method(mPolyphony, "backend_send", Polyphony_backend_send, 3);
|
|
146
139
|
rb_define_singleton_method(mPolyphony, "backend_sendv", Polyphony_backend_sendv, 3);
|
data/ext/polyphony/polyphony.h
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
#include "ruby.h"
|
|
7
7
|
#include "runqueue_ring_buffer.h"
|
|
8
|
+
#include "backend_common.h"
|
|
8
9
|
|
|
9
10
|
// debugging
|
|
10
11
|
#define OBJ_ID(obj) (NUM2LONG(rb_funcall(obj, rb_intern("object_id"), 0)))
|
|
@@ -18,10 +19,6 @@
|
|
|
18
19
|
free(strings); \
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
// tracing
|
|
22
|
-
#define TRACE(...) rb_funcall(rb_cObject, ID_fiber_trace, __VA_ARGS__)
|
|
23
|
-
#define COND_TRACE(...) if (__tracing_enabled__) { TRACE(__VA_ARGS__); }
|
|
24
|
-
|
|
25
22
|
// exceptions
|
|
26
23
|
#define TEST_EXCEPTION(ret) (rb_obj_is_kind_of(ret, rb_eException) == Qtrue)
|
|
27
24
|
#define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
|
|
@@ -36,14 +33,12 @@
|
|
|
36
33
|
extern VALUE mPolyphony;
|
|
37
34
|
extern VALUE cQueue;
|
|
38
35
|
extern VALUE cEvent;
|
|
39
|
-
extern VALUE cRunqueue;
|
|
40
36
|
extern VALUE cTimeoutException;
|
|
41
37
|
|
|
42
38
|
extern ID ID_call;
|
|
43
39
|
extern ID ID_caller;
|
|
44
40
|
extern ID ID_clear;
|
|
45
41
|
extern ID ID_each;
|
|
46
|
-
extern ID ID_fiber_trace;
|
|
47
42
|
extern ID ID_inspect;
|
|
48
43
|
extern ID ID_invoke;
|
|
49
44
|
extern ID ID_ivar_backend;
|
|
@@ -67,14 +62,6 @@ extern VALUE SYM_fiber_schedule;
|
|
|
67
62
|
extern VALUE SYM_fiber_switchpoint;
|
|
68
63
|
extern VALUE SYM_fiber_terminate;
|
|
69
64
|
|
|
70
|
-
extern int __tracing_enabled__;
|
|
71
|
-
|
|
72
|
-
enum {
|
|
73
|
-
FIBER_STATE_NOT_SCHEDULED = 0,
|
|
74
|
-
FIBER_STATE_WAITING = 1,
|
|
75
|
-
FIBER_STATE_SCHEDULED = 2
|
|
76
|
-
};
|
|
77
|
-
|
|
78
65
|
VALUE Fiber_auto_watcher(VALUE self);
|
|
79
66
|
void Fiber_make_runnable(VALUE fiber, VALUE value);
|
|
80
67
|
|
|
@@ -104,10 +91,10 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
|
104
91
|
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
105
92
|
VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
|
|
106
93
|
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
|
107
|
-
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof);
|
|
108
|
-
VALUE Backend_read_loop(VALUE self, VALUE io);
|
|
109
|
-
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length);
|
|
110
|
-
VALUE Backend_recv_loop(VALUE self, VALUE io);
|
|
94
|
+
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos);
|
|
95
|
+
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen);
|
|
96
|
+
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos);
|
|
97
|
+
VALUE Backend_recv_loop(VALUE self, VALUE io, VALUE maxlen);
|
|
111
98
|
VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
|
112
99
|
VALUE Backend_send(VALUE self, VALUE io, VALUE msg, VALUE flags);
|
|
113
100
|
VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags);
|
|
@@ -121,11 +108,13 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write);
|
|
|
121
108
|
VALUE Backend_waitpid(VALUE self, VALUE pid);
|
|
122
109
|
VALUE Backend_write_m(int argc, VALUE *argv, VALUE self);
|
|
123
110
|
|
|
124
|
-
|
|
125
|
-
VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
|
|
111
|
+
VALUE Backend_poll(VALUE self, VALUE blocking);
|
|
126
112
|
VALUE Backend_wait_event(VALUE self, VALUE raise_on_exception);
|
|
127
113
|
VALUE Backend_wakeup(VALUE self);
|
|
128
114
|
VALUE Backend_run_idle_tasks(VALUE self);
|
|
115
|
+
VALUE Backend_switch_fiber(VALUE self);
|
|
116
|
+
void Backend_schedule_fiber(VALUE thread, VALUE self, VALUE fiber, VALUE value, int prioritize);
|
|
117
|
+
void Backend_unschedule_fiber(VALUE self, VALUE fiber);
|
|
129
118
|
|
|
130
119
|
VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
|
131
120
|
VALUE Thread_schedule_fiber_with_priority(VALUE thread, VALUE fiber, VALUE value);
|
|
@@ -5,10 +5,8 @@ void Init_Polyphony();
|
|
|
5
5
|
void Init_Backend();
|
|
6
6
|
void Init_Queue();
|
|
7
7
|
void Init_Event();
|
|
8
|
-
void Init_Runqueue();
|
|
9
8
|
void Init_SocketExtensions();
|
|
10
9
|
void Init_Thread();
|
|
11
|
-
void Init_Tracing();
|
|
12
10
|
|
|
13
11
|
#ifdef POLYPHONY_PLAYGROUND
|
|
14
12
|
extern void playground();
|
|
@@ -20,10 +18,8 @@ void Init_polyphony_ext() {
|
|
|
20
18
|
Init_Backend();
|
|
21
19
|
Init_Queue();
|
|
22
20
|
Init_Event();
|
|
23
|
-
Init_Runqueue();
|
|
24
21
|
Init_Fiber();
|
|
25
22
|
Init_Thread();
|
|
26
|
-
Init_Tracing();
|
|
27
23
|
|
|
28
24
|
Init_SocketExtensions();
|
|
29
25
|
|
data/ext/polyphony/queue.c
CHANGED
|
@@ -57,21 +57,21 @@ static VALUE Queue_initialize(int argc, VALUE *argv, VALUE self) {
|
|
|
57
57
|
return self;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
inline void
|
|
60
|
+
inline void queue_schedule_first_blocked_fiber(ring_buffer *queue) {
|
|
61
61
|
if (queue->count) {
|
|
62
62
|
VALUE fiber = ring_buffer_shift(queue);
|
|
63
63
|
if (fiber != Qnil) Fiber_make_runnable(fiber, Qnil);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
inline void
|
|
67
|
+
inline void queue_schedule_all_blocked_fibers(ring_buffer *queue) {
|
|
68
68
|
while (queue->count) {
|
|
69
69
|
VALUE fiber = ring_buffer_shift(queue);
|
|
70
70
|
if (fiber != Qnil) Fiber_make_runnable(fiber, Qnil);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
inline void
|
|
74
|
+
inline void queue_schedule_blocked_fibers_to_capacity(Queue_t *queue) {
|
|
75
75
|
for (unsigned int i = queue->values.count; (i < queue->capacity) && queue->push_queue.count; i++) {
|
|
76
76
|
VALUE fiber = ring_buffer_shift(&queue->push_queue);
|
|
77
77
|
if (fiber != Qnil) Fiber_make_runnable(fiber, Qnil);
|
|
@@ -101,7 +101,7 @@ VALUE Queue_push(VALUE self, VALUE value) {
|
|
|
101
101
|
|
|
102
102
|
if (queue->capacity) capped_queue_block_push(queue);
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
queue_schedule_first_blocked_fiber(&queue->shift_queue);
|
|
105
105
|
ring_buffer_push(&queue->values, value);
|
|
106
106
|
|
|
107
107
|
return self;
|
|
@@ -113,7 +113,7 @@ VALUE Queue_unshift(VALUE self, VALUE value) {
|
|
|
113
113
|
|
|
114
114
|
if (queue->capacity) capped_queue_block_push(queue);
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
queue_schedule_first_blocked_fiber(&queue->shift_queue);
|
|
117
117
|
ring_buffer_unshift(&queue->values, value);
|
|
118
118
|
|
|
119
119
|
return self;
|
|
@@ -140,7 +140,7 @@ VALUE Queue_shift(VALUE self) {
|
|
|
140
140
|
}
|
|
141
141
|
VALUE value = ring_buffer_shift(&queue->values);
|
|
142
142
|
if ((queue->capacity) && (queue->capacity > queue->values.count))
|
|
143
|
-
|
|
143
|
+
queue_schedule_first_blocked_fiber(&queue->push_queue);
|
|
144
144
|
RB_GC_GUARD(value);
|
|
145
145
|
return value;
|
|
146
146
|
}
|
|
@@ -152,7 +152,7 @@ VALUE Queue_delete(VALUE self, VALUE value) {
|
|
|
152
152
|
ring_buffer_delete(&queue->values, value);
|
|
153
153
|
|
|
154
154
|
if (queue->capacity && (queue->capacity > queue->values.count))
|
|
155
|
-
|
|
155
|
+
queue_schedule_first_blocked_fiber(&queue->push_queue);
|
|
156
156
|
|
|
157
157
|
return self;
|
|
158
158
|
}
|
|
@@ -164,9 +164,9 @@ VALUE Queue_cap(VALUE self, VALUE cap) {
|
|
|
164
164
|
queue->capacity = new_capacity;
|
|
165
165
|
|
|
166
166
|
if (queue->capacity)
|
|
167
|
-
|
|
167
|
+
queue_schedule_blocked_fibers_to_capacity(queue);
|
|
168
168
|
else
|
|
169
|
-
|
|
169
|
+
queue_schedule_all_blocked_fibers(&queue->push_queue);
|
|
170
170
|
|
|
171
171
|
return self;
|
|
172
172
|
}
|
|
@@ -183,7 +183,7 @@ VALUE Queue_clear(VALUE self) {
|
|
|
183
183
|
GetQueue(self, queue);
|
|
184
184
|
|
|
185
185
|
ring_buffer_clear(&queue->values);
|
|
186
|
-
if (queue->capacity)
|
|
186
|
+
if (queue->capacity) queue_schedule_blocked_fibers_to_capacity(queue);
|
|
187
187
|
|
|
188
188
|
return self;
|
|
189
189
|
}
|
|
@@ -200,7 +200,7 @@ VALUE Queue_shift_each(VALUE self) {
|
|
|
200
200
|
GetQueue(self, queue);
|
|
201
201
|
|
|
202
202
|
ring_buffer_shift_each(&queue->values);
|
|
203
|
-
if (queue->capacity)
|
|
203
|
+
if (queue->capacity) queue_schedule_blocked_fibers_to_capacity(queue);
|
|
204
204
|
return self;
|
|
205
205
|
}
|
|
206
206
|
|
|
@@ -209,7 +209,7 @@ VALUE Queue_shift_all(VALUE self) {
|
|
|
209
209
|
GetQueue(self, queue);
|
|
210
210
|
|
|
211
211
|
VALUE result = ring_buffer_shift_all(&queue->values);
|
|
212
|
-
if (queue->capacity)
|
|
212
|
+
if (queue->capacity) queue_schedule_blocked_fibers_to_capacity(queue);
|
|
213
213
|
return result;
|
|
214
214
|
}
|
|
215
215
|
|
data/ext/polyphony/runqueue.c
CHANGED
|
@@ -1,136 +1,59 @@
|
|
|
1
1
|
#include "polyphony.h"
|
|
2
|
-
#include "
|
|
2
|
+
#include "runqueue.h"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
unsigned int switch_count;
|
|
8
|
-
} Runqueue_t;
|
|
9
|
-
|
|
10
|
-
VALUE cRunqueue = Qnil;
|
|
11
|
-
|
|
12
|
-
static void Runqueue_mark(void *ptr) {
|
|
13
|
-
Runqueue_t *runqueue = ptr;
|
|
14
|
-
runqueue_ring_buffer_mark(&runqueue->entries);
|
|
4
|
+
inline void runqueue_initialize(runqueue_t *runqueue) {
|
|
5
|
+
runqueue_ring_buffer_init(&runqueue->entries);
|
|
6
|
+
runqueue->high_watermark = 0;
|
|
15
7
|
}
|
|
16
8
|
|
|
17
|
-
|
|
18
|
-
Runqueue_t *runqueue = ptr;
|
|
9
|
+
inline void runqueue_finalize(runqueue_t *runqueue) {
|
|
19
10
|
runqueue_ring_buffer_free(&runqueue->entries);
|
|
20
|
-
xfree(ptr);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
static size_t Runqueue_size(const void *ptr) {
|
|
24
|
-
return sizeof(Runqueue_t);
|
|
25
11
|
}
|
|
26
12
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{Runqueue_mark, Runqueue_free, Runqueue_size,},
|
|
30
|
-
0, 0, 0
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
static VALUE Runqueue_allocate(VALUE klass) {
|
|
34
|
-
Runqueue_t *runqueue;
|
|
35
|
-
|
|
36
|
-
runqueue = ALLOC(Runqueue_t);
|
|
37
|
-
return TypedData_Wrap_Struct(klass, &Runqueue_type, runqueue);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
#define GetRunqueue(obj, runqueue) \
|
|
41
|
-
TypedData_Get_Struct((obj), Runqueue_t, &Runqueue_type, (runqueue))
|
|
42
|
-
|
|
43
|
-
static VALUE Runqueue_initialize(VALUE self) {
|
|
44
|
-
Runqueue_t *runqueue;
|
|
45
|
-
GetRunqueue(self, runqueue);
|
|
46
|
-
|
|
47
|
-
runqueue_ring_buffer_init(&runqueue->entries);
|
|
48
|
-
runqueue->high_watermark = 0;
|
|
49
|
-
runqueue->switch_count = 0;
|
|
50
|
-
|
|
51
|
-
return self;
|
|
13
|
+
inline void runqueue_mark(runqueue_t *runqueue) {
|
|
14
|
+
runqueue_ring_buffer_mark(&runqueue->entries);
|
|
52
15
|
}
|
|
53
16
|
|
|
54
|
-
void
|
|
55
|
-
Runqueue_t *runqueue;
|
|
56
|
-
GetRunqueue(self, runqueue);
|
|
57
|
-
|
|
17
|
+
inline void runqueue_push(runqueue_t *runqueue, VALUE fiber, VALUE value, int reschedule) {
|
|
58
18
|
if (reschedule) runqueue_ring_buffer_delete(&runqueue->entries, fiber);
|
|
59
19
|
runqueue_ring_buffer_push(&runqueue->entries, fiber, value);
|
|
60
20
|
if (runqueue->entries.count > runqueue->high_watermark)
|
|
61
21
|
runqueue->high_watermark = runqueue->entries.count;
|
|
62
22
|
}
|
|
63
23
|
|
|
64
|
-
void
|
|
65
|
-
Runqueue_t *runqueue;
|
|
66
|
-
GetRunqueue(self, runqueue);
|
|
24
|
+
inline void runqueue_unshift(runqueue_t *runqueue, VALUE fiber, VALUE value, int reschedule) {
|
|
67
25
|
if (reschedule) runqueue_ring_buffer_delete(&runqueue->entries, fiber);
|
|
68
26
|
runqueue_ring_buffer_unshift(&runqueue->entries, fiber, value);
|
|
69
27
|
if (runqueue->entries.count > runqueue->high_watermark)
|
|
70
28
|
runqueue->high_watermark = runqueue->entries.count;
|
|
71
29
|
}
|
|
72
30
|
|
|
73
|
-
runqueue_entry
|
|
74
|
-
|
|
75
|
-
GetRunqueue(self, runqueue);
|
|
76
|
-
runqueue_entry entry = runqueue_ring_buffer_shift(&runqueue->entries);
|
|
77
|
-
if (entry.fiber == Qnil)
|
|
78
|
-
runqueue->high_watermark = 0;
|
|
79
|
-
else
|
|
80
|
-
runqueue->switch_count += 1;
|
|
81
|
-
return entry;
|
|
31
|
+
inline runqueue_entry runqueue_shift(runqueue_t *runqueue) {
|
|
32
|
+
return runqueue_ring_buffer_shift(&runqueue->entries);
|
|
82
33
|
}
|
|
83
34
|
|
|
84
|
-
void
|
|
85
|
-
Runqueue_t *runqueue;
|
|
86
|
-
GetRunqueue(self, runqueue);
|
|
35
|
+
inline void runqueue_delete(runqueue_t *runqueue, VALUE fiber) {
|
|
87
36
|
runqueue_ring_buffer_delete(&runqueue->entries, fiber);
|
|
88
37
|
}
|
|
89
38
|
|
|
90
|
-
int
|
|
91
|
-
Runqueue_t *runqueue;
|
|
92
|
-
GetRunqueue(self, runqueue);
|
|
39
|
+
inline int runqueue_index_of(runqueue_t *runqueue, VALUE fiber) {
|
|
93
40
|
return runqueue_ring_buffer_index_of(&runqueue->entries, fiber);
|
|
94
41
|
}
|
|
95
42
|
|
|
96
|
-
void
|
|
97
|
-
Runqueue_t *runqueue;
|
|
98
|
-
GetRunqueue(self, runqueue);
|
|
43
|
+
inline void runqueue_clear(runqueue_t *runqueue) {
|
|
99
44
|
runqueue_ring_buffer_clear(&runqueue->entries);
|
|
100
45
|
}
|
|
101
46
|
|
|
102
|
-
long
|
|
103
|
-
Runqueue_t *runqueue;
|
|
104
|
-
GetRunqueue(self, runqueue);
|
|
105
|
-
|
|
47
|
+
inline long runqueue_len(runqueue_t *runqueue) {
|
|
106
48
|
return runqueue->entries.count;
|
|
107
49
|
}
|
|
108
50
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return (runqueue->entries.count == 0);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
static const unsigned int ANTI_STARVE_HIGH_WATERMARK_THRESHOLD = 128;
|
|
117
|
-
static const unsigned int ANTI_STARVE_SWITCH_COUNT_THRESHOLD = 64;
|
|
118
|
-
|
|
119
|
-
int Runqueue_should_poll_nonblocking(VALUE self) {
|
|
120
|
-
Runqueue_t *runqueue;
|
|
121
|
-
GetRunqueue(self, runqueue);
|
|
122
|
-
|
|
123
|
-
if (runqueue->high_watermark < ANTI_STARVE_HIGH_WATERMARK_THRESHOLD) return 0;
|
|
124
|
-
if (runqueue->switch_count < ANTI_STARVE_SWITCH_COUNT_THRESHOLD) return 0;
|
|
125
|
-
|
|
126
|
-
// the
|
|
127
|
-
runqueue->switch_count = 0;
|
|
128
|
-
return 1;
|
|
51
|
+
inline long runqueue_max_len(runqueue_t *runqueue) {
|
|
52
|
+
unsigned int max_len = runqueue->high_watermark;
|
|
53
|
+
runqueue->high_watermark = 0;
|
|
54
|
+
return max_len;
|
|
129
55
|
}
|
|
130
56
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
rb_define_alloc_func(cRunqueue, Runqueue_allocate);
|
|
134
|
-
|
|
135
|
-
rb_define_method(cRunqueue, "initialize", Runqueue_initialize, 0);
|
|
57
|
+
inline int runqueue_empty_p(runqueue_t *runqueue) {
|
|
58
|
+
return (runqueue->entries.count == 0);
|
|
136
59
|
}
|