From 6b3ef2249cc6d03b9e153a1bbfb24eb12d4032a5 Mon Sep 17 00:00:00 2001 From: ko1 Date: Sat, 2 Jun 2007 07:48:29 +0000 Subject: [PATCH] * cont.c (Fiber#pass): rename to Fiber#yield. Block parameter of fiber body receive first yield values. e.g.: Fiber.new{|x| p x}.yield(:ok) #=> :ok * cont.c: rename rb_context_t#retval to rb_context_t#value. * test/ruby/test_fiber.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12425 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 ++++++ cont.c | 70 ++++++++++++++++++++++------------------- test/ruby/test_fiber.rb | 35 ++++++++++++--------- 3 files changed, 68 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 66fe8e40b5..be313858fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Sat Jun 2 16:48:55 2007 Koichi Sasada + + * cont.c (Fiber#pass): rename to Fiber#yield. Block parameter + of fiber body receive first yield values. + e.g.: Fiber.new{|x| p x}.yield(:ok) #=> :ok + + * cont.c: rename rb_context_t#retval to rb_context_t#value. + + * test/ruby/test_fiber.rb: ditto. + Sat Jun 2 16:45:21 2007 Koichi Sasada * proc.c (Init_Proc): remove a line break. diff --git a/cont.c b/cont.c index 9f1efac8b8..4327d14746 100644 --- a/cont.c +++ b/cont.c @@ -17,7 +17,7 @@ typedef struct rb_context_struct { VALUE self; - VALUE retval; + VALUE value; VALUE prev; /* for fiber */ VALUE *vm_stack; VALUE *machine_stack; @@ -30,6 +30,7 @@ typedef struct rb_context_struct { VALUE rb_cCont; VALUE rb_cFiber; +VALUE rb_eFiberError; #define GetContPtr(obj, ptr) \ Data_Get_Struct(obj, rb_context_t, ptr) @@ -44,7 +45,7 @@ cont_mark(void *ptr) MARK_REPORT_ENTER("cont"); if (ptr) { rb_context_t *cont = ptr; - rb_gc_mark(cont->retval); + rb_gc_mark(cont->value); rb_gc_mark(cont->prev); rb_thread_mark(&cont->saved_thread); @@ -139,12 +140,12 @@ cont_capture(volatile int *stat) cont_save_machine_stack(th, cont); if (ruby_setjmp(cont->jmpbuf)) { - VALUE retval; + VALUE value; - retval = cont->retval; - cont->retval = Qnil; + value = cont->value; + cont->value = Qnil; *stat = 1; - return retval; + return value; } else { *stat = 0; @@ -344,7 +345,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) rb_raise(rb_eRuntimeError, "continuation called across trap"); } - cont->retval = make_passing_arg(argc, argv); + cont->value = make_passing_arg(argc, argv); cont_restore_0(cont, (VALUE *)&cont); return Qnil; /* unreachable */ @@ -357,11 +358,10 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) #define FIBER_STACK_SIZE (4 * 1024) static VALUE -rb_fiber_s_new(int argc, VALUE *argv, VALUE self) +rb_fiber_s_new(VALUE self) { - rb_context_t *cont = cont_new(rb_cFiber); + rb_context_t *cont = cont_new(self); rb_thread_t *th = &cont->saved_thread; - volatile VALUE fval = cont->self; /* initialize */ cont->prev = Qnil; @@ -385,20 +385,19 @@ rb_fiber_s_new(int argc, VALUE *argv, VALUE self) th->cfp->block_iseq = 0; th->first_proc = rb_block_proc(); - th->first_args = rb_ary_new4(argc, argv); MEMCPY(&cont->jmpbuf, &th->root_jmpbuf, rb_jmpbuf_t, 1); return cont->self; } -static VALUE rb_fiber_pass(int argc, VALUE *args, VALUE fval); +static VALUE rb_fiber_yield(int argc, VALUE *args, VALUE fval); static void rb_fiber_terminate(rb_context_t *cont) { rb_context_t *prev_cont; - VALUE retval = cont->retval; + VALUE value = cont->value; GetContPtr(cont->prev, prev_cont); @@ -406,10 +405,10 @@ rb_fiber_terminate(rb_context_t *cont) if (prev_cont->alive == Qfalse) { - rb_fiber_pass(1, &retval, GET_THREAD()->root_fiber); + rb_fiber_yield(1, &value, GET_THREAD()->root_fiber); } else { - rb_fiber_pass(1, &retval, cont->prev); + rb_fiber_yield(1, &value, cont->prev); } } @@ -426,12 +425,13 @@ rb_fiber_start(void) if ((state = EXEC_TAG()) == 0) { GetContPtr(th->fiber, cont); GetProcPtr(cont->saved_thread.first_proc, proc); - args = cont->saved_thread.first_args; + args = cont->value; + cont->value = Qnil; th->errinfo = Qnil; th->local_lfp = proc->block.lfp; th->local_svar = Qnil; - cont->retval = th_invoke_proc(th, proc, proc->block.self, - RARRAY_LEN(args), RARRAY_PTR(args)); + + cont->value = th_invoke_proc(th, proc, proc->block.self, 1, &args); } TH_POP_TAG(); @@ -478,7 +478,7 @@ cont_store(rb_context_t *next_cont) if (ruby_setjmp(cont->jmpbuf)) { /* restored */ GetContPtr(th->fiber, cont); - return cont->retval; + return cont->value; } else { return Qundef; @@ -486,29 +486,32 @@ cont_store(rb_context_t *next_cont) } static VALUE -rb_fiber_pass(int argc, VALUE *argv, VALUE fval) +rb_fiber_yield(int argc, VALUE *argv, VALUE fval) { - VALUE retval; + VALUE value; rb_context_t *cont; rb_thread_t *th = GET_THREAD(); GetContPtr(fval, cont); if (cont->saved_thread.self != th->self) { - rb_raise(rb_eRuntimeError, "fiber called across threads"); + rb_raise(rb_eFiberError, "fiber called across threads"); } if (cont->saved_thread.trap_tag != th->trap_tag) { - rb_raise(rb_eRuntimeError, "fiber called across trap"); + rb_raise(rb_eFiberError, "fiber called across trap"); + } + if (!cont->alive) { + rb_raise(rb_eFiberError, "dead fiber called"); } - cont->retval = make_passing_arg(argc, argv); + cont->value = make_passing_arg(argc, argv); - if ((retval = cont_store(cont)) == Qundef) { + if ((value = cont_store(cont)) == Qundef) { cont_restore_0(cont, (VALUE *)&cont); - rb_bug("rb_fiber_pass: unreachable"); + rb_bug("rb_fiber_yield: unreachable"); } - return retval; + return value; } static VALUE @@ -540,9 +543,9 @@ rb_fiber_s_prev(VALUE klass) } static VALUE -rb_fiber_s_pass(int argc, VALUE *argv, VALUE fval) +rb_fiber_s_yield(int argc, VALUE *argv, VALUE fval) { - return rb_fiber_pass(argc, argv, rb_fiber_s_prev(Qnil)); + return rb_fiber_yield(argc, argv, rb_fiber_s_prev(Qnil)); } void @@ -557,14 +560,15 @@ Init_Cont(void) rb_cFiber = rb_define_class("Fiber", rb_cObject); rb_undef_alloc_func(rb_cFiber); - rb_define_method(rb_cFiber, "pass", rb_fiber_pass, -1); + rb_define_method(rb_cFiber, "yield", rb_fiber_yield, -1); rb_define_method(rb_cFiber, "prev", rb_fiber_prev, 0); rb_define_method(rb_cFiber, "alive?", rb_fiber_alive_p, 0); rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0); rb_define_singleton_method(rb_cFiber, "prev", rb_fiber_s_prev, 0); - rb_define_singleton_method(rb_cFiber, "pass", rb_fiber_s_pass, -1); - rb_define_singleton_method(rb_cFiber, "new", rb_fiber_s_new, -1); - rb_define_singleton_method(rb_cFiber, "start", rb_fiber_s_new, -1); + rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1); + rb_define_singleton_method(rb_cFiber, "new", rb_fiber_s_new, 0); + + rb_eFiberError = rb_define_class("FiberError", rb_eStandardError); } diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb index 38d7cd9b62..999bfd267a 100644 --- a/test/ruby/test_fiber.rb +++ b/test/ruby/test_fiber.rb @@ -4,25 +4,27 @@ class TestFiber < Test::Unit::TestCase def test_normal f = Fiber.current assert_equal(:ok2, - Fiber.new(:ok1){|e| + Fiber.new{|e| assert_equal(:ok1, e) assert_equal(f, Fiber.prev) - Fiber.pass :ok2 - }.pass) + Fiber.yield :ok2 + }.yield(:ok1) + ) + assert_equal([:a, :b], Fiber.new{|a, b| [a, b]}.yield(:a, :b)) end def test_term - assert_equal(:ok, Fiber.new{:ok}.pass) + assert_equal(:ok, Fiber.new{:ok}.yield) assert_equal([:a, :b, :c, :d, :e], Fiber.new{ Fiber.new{ Fiber.new{ Fiber.new{ [:a] - }.pass + [:b] - }.pass + [:c] - }.pass + [:d] - }.pass + [:e]) + }.yield + [:b] + }.yield + [:c] + }.yield + [:d] + }.yield + [:e]) end def test_many_fibers @@ -33,7 +35,7 @@ class TestFiber < Test::Unit::TestCase assert_equal(max, max.times{|i| Fiber.new{ - }.pass + }.yield } ) end @@ -42,9 +44,14 @@ class TestFiber < Test::Unit::TestCase assert_raise(ArgumentError){ Fiber.new # Fiber without block } - assert_raise(RuntimeError){ + assert_raise(FiberError){ f = Fiber.new{} - Thread.new{f.pass}.join # Fiber passing across thread + Thread.new{f.yield}.join # Fiber yielding across thread + } + assert_raise(FiberError){ + f = Fiber.new{} + f.yield + f.yield } end @@ -52,14 +59,14 @@ class TestFiber < Test::Unit::TestCase ary = [] f2 = nil f1 = Fiber.new{ - ary << f2.pass(:foo) + ary << f2.yield(:foo) :bar } f2 = Fiber.new{ - ary << f1.pass(:baz) + ary << f1.yield(:baz) :ok } - assert_equal(:ok, f1.pass) + assert_equal(:ok, f1.yield) assert_equal([:baz, :bar], ary) end end