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);