polyphony 0.58 → 0.61
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|