ext/gyro/thread.c in polyphony-0.27 vs ext/gyro/thread.c in polyphony-0.28
- old
+ new
@@ -1,22 +1,22 @@
#include "gyro.h"
static VALUE cQueue;
static ID ID_create_event_selector;
-static ID ID_ivar_event_selector;
-static ID ID_ivar_event_selector_proc;
+static ID ID_empty;
static ID ID_fiber_ref_count;
-static ID ID_run_queue;
+static ID ID_ivar_event_selector_proc;
+static ID ID_ivar_event_selector;
static ID ID_ivar_main_fiber;
-static ID ID_stop;
-
-static ID ID_scheduled;
-
-static ID ID_empty;
static ID ID_pop;
static ID ID_push;
+static ID ID_run_queue;
+// static ID ID_run_queue_head;
+// static ID ID_run_queue_tail;
+static ID ID_runnable_next;
+static ID ID_stop;
VALUE event_selector_factory_proc(RB_BLOCK_CALL_FUNC_ARGLIST(args, klass)) {
return rb_funcall(klass, ID_new, 1, rb_ary_entry(args, 0));
}
@@ -95,48 +95,63 @@
rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
return stats;
}
-inline VALUE Thread_schedule_fiber(VALUE self, VALUE fiber) {
- VALUE queue = rb_ivar_get(self, ID_run_queue);
- rb_ary_push(queue, fiber);
+inline VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
+ // if fiber is already scheduled, just set the scheduled value, then return
+ rb_ivar_set(fiber, ID_runnable_value, value);
+ if (rb_ivar_get(fiber, ID_runnable) == Qnil) {
+ VALUE queue = rb_ivar_get(self, ID_run_queue);
+ rb_ary_push(queue, fiber);
+ rb_ivar_set(fiber, ID_runnable, Qtrue);
+ }
return self;
}
VALUE Thread_switch_fiber(VALUE self) {
+ VALUE current_fiber;
+ if (__tracing_enabled__) {
+ current_fiber = rb_fiber_current();
+ if (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse) {
+ rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_switchpoint, current_fiber);
+ }
+ }
VALUE queue = rb_ivar_get(self, ID_run_queue);
VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
- long scheduled_count;
+ VALUE next_fiber;
while (1) {
- scheduled_count = RARRAY_LEN(queue);
+ next_fiber = rb_ary_shift(queue);
// if (break_flag != 0) {
// return Qnil;
// }
- if ((scheduled_count > 0) || (Thread_fiber_ref_count(self) == 0)) {
+ if ((next_fiber != Qnil) || (Thread_fiber_ref_count(self) == 0)) {
break;
}
+ if (__tracing_enabled__) {
+ rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_ev_loop_enter, current_fiber);
+ }
Gyro_Selector_run(selector);
+ if (__tracing_enabled__) {
+ rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_ev_loop_leave, current_fiber);
+ }
}
- VALUE next_fiber;
- // while (1) {
- if (scheduled_count == 0) {
- return Qnil;
- }
- next_fiber = rb_ary_shift(queue);
- // break;
- // if (rb_fiber_alive_p(next_fiber) == Qtrue) {
- // break;
- // }
- // }
+ if (next_fiber == Qnil) {
+ return Qnil;
+ }
// run next fiber
- VALUE value = rb_ivar_get(next_fiber, ID_scheduled_value);
- rb_ivar_set(next_fiber, ID_scheduled, Qnil);
+ VALUE value = rb_ivar_get(next_fiber, ID_runnable_value);
+
+ if (__tracing_enabled__) {
+ rb_funcall(rb_cObject, ID_fiber_trace, 3, SYM_fiber_run, next_fiber, value);
+ }
+
+ rb_ivar_set(next_fiber, ID_runnable, Qnil);
RB_GC_GUARD(next_fiber);
RB_GC_GUARD(value);
return rb_funcall(next_fiber, ID_transfer, 1, value);
}
@@ -178,23 +193,23 @@
rb_define_method(rb_cThread, "setup_fiber_scheduling", Thread_setup_fiber_scheduling, 0);
rb_define_method(rb_cThread, "stop_event_selector", Thread_stop_event_selector, 0);
rb_define_method(rb_cThread, "reset_fiber_scheduling", Thread_reset_fiber_scheduling, 0);
rb_define_method(rb_cThread, "fiber_scheduling_stats", Thread_fiber_scheduling_stats, 0);
- rb_define_method(rb_cThread, "schedule_fiber", Thread_schedule_fiber, 1);
+ rb_define_method(rb_cThread, "schedule_fiber", Thread_schedule_fiber, 2);
rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
ID_create_event_selector = rb_intern("create_event_selector");
+ ID_empty = rb_intern("empty?");
+ ID_fiber_ref_count = rb_intern("fiber_ref_count");
ID_ivar_event_selector = rb_intern("@event_selector");
ID_ivar_event_selector_proc = rb_intern("@event_selector_proc");
ID_ivar_main_fiber = rb_intern("@main_fiber");
- ID_fiber_ref_count = rb_intern("fiber_ref_count");
- ID_run_queue = rb_intern("run_queue");
- ID_scheduled = rb_intern("scheduled");
- ID_empty = rb_intern("empty?");
ID_pop = rb_intern("pop");
ID_push = rb_intern("push");
+ ID_run_queue = rb_intern("run_queue");
+ ID_runnable_next = rb_intern("runnable_next");
ID_stop = rb_intern("stop");
SYM_scheduled_fibers = ID2SYM(rb_intern("scheduled_fibers"));
SYM_pending_watchers = ID2SYM(rb_intern("pending_watchers"));
rb_global_variable(&SYM_scheduled_fibers);