polyphony 0.58 → 0.61

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/Gemfile.lock +15 -29
  4. data/examples/core/message_based_supervision.rb +51 -0
  5. data/examples/io/echo_server.rb +16 -7
  6. data/ext/polyphony/backend_common.c +160 -7
  7. data/ext/polyphony/backend_common.h +34 -2
  8. data/ext/polyphony/backend_io_uring.c +119 -40
  9. data/ext/polyphony/backend_io_uring_context.c +10 -1
  10. data/ext/polyphony/backend_io_uring_context.h +5 -3
  11. data/ext/polyphony/backend_libev.c +109 -31
  12. data/ext/polyphony/extconf.rb +2 -2
  13. data/ext/polyphony/fiber.c +1 -34
  14. data/ext/polyphony/polyphony.c +12 -19
  15. data/ext/polyphony/polyphony.h +9 -20
  16. data/ext/polyphony/polyphony_ext.c +0 -4
  17. data/ext/polyphony/queue.c +12 -12
  18. data/ext/polyphony/runqueue.c +21 -98
  19. data/ext/polyphony/runqueue.h +26 -0
  20. data/ext/polyphony/thread.c +6 -113
  21. data/lib/polyphony/core/timer.rb +2 -2
  22. data/lib/polyphony/extensions/fiber.rb +102 -82
  23. data/lib/polyphony/extensions/io.rb +10 -9
  24. data/lib/polyphony/extensions/openssl.rb +14 -4
  25. data/lib/polyphony/extensions/socket.rb +15 -15
  26. data/lib/polyphony/extensions/thread.rb +1 -1
  27. data/lib/polyphony/version.rb +1 -1
  28. data/polyphony.gemspec +0 -7
  29. data/test/test_backend.rb +46 -9
  30. data/test/test_ext.rb +1 -1
  31. data/test/test_fiber.rb +106 -18
  32. data/test/test_global_api.rb +1 -1
  33. data/test/test_io.rb +29 -0
  34. data/test/test_supervise.rb +100 -100
  35. data/test/test_thread.rb +5 -11
  36. data/test/test_thread_pool.rb +1 -1
  37. data/test/test_trace.rb +28 -49
  38. metadata +5 -109
  39. data/ext/polyphony/tracing.c +0 -11
  40. data/lib/polyphony/adapters/trace.rb +0 -138
@@ -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\.([\d+])/
12
- kernel_minor_version = $1.gsub('.', '').to_i
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
@@ -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");
@@ -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, 4);
141
- rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 1);
142
- rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 3);
143
- rb_define_singleton_method(mPolyphony, "backend_recv_loop", Polyphony_backend_recv_loop, 1);
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);
@@ -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
- unsigned int Backend_pending_count(VALUE self);
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
 
@@ -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 queue_resume_first_blocked_fiber(ring_buffer *queue) {
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 queue_resume_all_blocked_fibers(ring_buffer *queue) {
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 queue_resume_blocked_fibers_to_capacity(Queue_t *queue) {
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
- queue_resume_first_blocked_fiber(&queue->shift_queue);
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
- queue_resume_first_blocked_fiber(&queue->shift_queue);
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
- queue_resume_first_blocked_fiber(&queue->push_queue);
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
- queue_resume_first_blocked_fiber(&queue->push_queue);
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
- queue_resume_blocked_fibers_to_capacity(queue);
167
+ queue_schedule_blocked_fibers_to_capacity(queue);
168
168
  else
169
- queue_resume_all_blocked_fibers(&queue->push_queue);
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) queue_resume_blocked_fibers_to_capacity(queue);
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) queue_resume_blocked_fibers_to_capacity(queue);
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) queue_resume_blocked_fibers_to_capacity(queue);
212
+ if (queue->capacity) queue_schedule_blocked_fibers_to_capacity(queue);
213
213
  return result;
214
214
  }
215
215
 
@@ -1,136 +1,59 @@
1
1
  #include "polyphony.h"
2
- #include "runqueue_ring_buffer.h"
2
+ #include "runqueue.h"
3
3
 
4
- typedef struct queue {
5
- runqueue_ring_buffer entries;
6
- unsigned int high_watermark;
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
- static void Runqueue_free(void *ptr) {
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
- static const rb_data_type_t Runqueue_type = {
28
- "Runqueue",
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 Runqueue_push(VALUE self, VALUE fiber, VALUE value, int reschedule) {
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 Runqueue_unshift(VALUE self, VALUE fiber, VALUE value, int reschedule) {
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 Runqueue_shift(VALUE self) {
74
- Runqueue_t *runqueue;
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 Runqueue_delete(VALUE self, VALUE fiber) {
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 Runqueue_index_of(VALUE self, VALUE fiber) {
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 Runqueue_clear(VALUE self) {
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 Runqueue_len(VALUE self) {
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
- int Runqueue_empty_p(VALUE self) {
110
- Runqueue_t *runqueue;
111
- GetRunqueue(self, runqueue);
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
- void Init_Runqueue() {
132
- cRunqueue = rb_define_class_under(mPolyphony, "Runqueue", rb_cObject);
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
  }