Nested fiber invocation

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

e$B1sF#$5$s$+$ie(B

http://d.hatena.ne.jp/ku-ma-me/20070817/p2

e$B$G;XE&$5$l$F$$$k$N$G$9$,!“e(BEnumerator#nexte$B$NFbB&$G$5$i$Ke(B
Enumerator#nexte$B$,8F$P$l$k$H!”%(%i!<$K$J$j$^$9!#%G%P%C%,$GDI$$e(B
e$B$+$1$k$He(B rb_fiber_yield()
e$B$+$iEO$7$?CM$H0c$&$b$Ne(B(yielde$B$5$l$?e(B
e$BCM!)e(B)e$B$,5"$C$F$-$F$$$k$h$&$G$9!#e(B

def (o = Object.new).each
yield 0
p [1,2,3].to_enum.next
end

p o.to_enum.next # => double.rb:6:in `’: unhandled exception

current
fibere$B$re(Byielde$B$7$F$$$k$O$:$J$N$K!"e(BFIXNUMe$B$Ne(B0(yielde$B$7$?e(B
e$BCM!)e(B)e$B$,EO$5$l$k!#e(B0e$B$Oe(BFibere$B$G$O$J$$$N$Ge(BTypeErrore$BNc30$,H/@8$7$Fe(B
e$B$$$k!#e(B

e$B;d$Ne(BFibere$B$NCN<1$G$O$3$3$^$G$,8B3&$G$7$?!#$3$l$O%P%0$G$7$g$&e(B
e$B$+!"[email protected])8B$H$9$Y$-$G$7$g$&$+!#$G$-$l$P!"%M%9%H$G$-$J$$e(B
[email protected]$&@)8B$O$J$$J}$,$&$l$7$$$N$G$9$,!#e(B

                            e$B$^$D$b$He(B e$B$f$-$R$me(B /:|)

[email protected]$G$9!#e(B

Yukihiro M. wrote:

e$B;d$Ne(BFibere$B$NCN<1$G$O$3$3$^$G$,8B3&$G$7$?!#$3$l$O%P%0$G$7$g$&e(B
e$B$+!"[email protected])8B$H$9$Y$-$G$7$g$&$+!#$G$-$l$P!"%M%9%H$G$-$J$$e(B
[email protected]$&@)8B$O$J$$J}$,$&$l$7$$$N$G$9$,!#e(B

                            e$B$^$D$b$He(B e$B$f$-$R$me(B /:|)

e$B!!$3$s$J46$8$G$I$&$G$7$g$&!#$D$^$j!"%V%m%C%/$N:G8e$be(B
rb_fiber_yield
e$B$GLa$k$h$&$K$7$^$7$g$&$C$F46$8$G!#e(B

Index: enumerator.c

— enumerator.c (e$B%j%S%8%g%se(B 13113)
+++ enumerator.c (e$B:n6H%3%T!<e(B)
@@ -13,6 +13,7 @@
************************************************/

#include “ruby/ruby.h”
+#include “debug.h”

/*

  • Document-class: Enumerable::Enumerator
    @@ -42,6 +43,7 @@
    VALUE fib;
    VALUE next;
    VALUE dst;
  • VALUE has_next;
    };

static void
@@ -237,6 +239,7 @@
if (argc) ptr->args = rb_ary_new4(argc, argv);
ptr->fib = 0;
ptr->next = ptr->dst = Qnil;

  • ptr->has_next = Qnil;

    return enum_obj;
    }
    @@ -381,19 +384,20 @@
    next_i(VALUE curr, VALUE obj)
    {
    struct enumerator *e = enumerator_ptr(obj);

  • e->dst = curr;

  • e->dst = curr;
    rb_block_call(obj, rb_intern(“each”), 0, 0, next_ii, obj);
  • return e->next;
  • e->has_next = Qfalse;
  • rb_fiber_yield(e->dst, 1, &e->next);
    }

static void
next_init(VALUE obj, struct enumerator *e)
{
VALUE curr = rb_fiber_current();

 e->dst = curr;
 e->fib = rb_block_call(rb_cFiber, rb_intern("new"), 0, 0,

next_i, obj);

  • e->has_next = Qtrue;
    rb_fiber_yield(e->fib, 1, &curr);
    }

@@ -416,16 +420,18 @@
{
struct enumerator *e = enumerator_ptr(obj);
VALUE curr, v;

  • curr = rb_fiber_current();
  • curr = rb_fiber_current();
    if (!e->fib) {
    next_init(obj, e);
    }
  • if (!rb_fiber_alive_p(e->fib)) {
  • if (!e->has_next) {
    e->fib = 0;
    e->next = e->dst = Qnil;
    rb_raise(rb_eStopIteration, “Enumerator#each reached at end”);
    }
  • v = rb_fiber_yield(e->fib, 1, &curr);
    return v;
    }
    @@ -441,11 +447,7 @@
    enumerator_next_p(VALUE obj)
    {
    struct enumerator *e = enumerator_ptr(obj);
  • if (!e->fib) {
  • next_init(obj, e);
  • }
  • return rb_fiber_alive_p(e->fib);
  • return e->has_next;
    }

/*

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:31508] Re: nested fiber invocation”
on Sun, 19 Aug 2007 21:16:13 +0900, SASADA Koichi [email protected]
writes:

|e$B!!$3$s$J46$8$G$I$&$G$7$g$&!#$D$^$j!"%V%m%C%/$N:G8e$be(B rb_fiber_yield
|e$B$GLa$k$h$&$K$7$^$7$g$&$C$F46$8$G!#e(B

e$B$$!"$A$c$s$HF0$/!#$G$b!"$I$&$7$F:#$^[email protected]$H%@%a$G!V%V%m%Ce(B
e$B%/$N:G8e$be(B rb_fiber_yield e$B$GLa$k!W$HBg>fIW$J$N$+$O$h$/$o$+$ie(B
e$B$J$$$s$G$9$1$I!#e(B

e$B$"$H!"<B:]$KFI$_9~$`A0$Ne(Bnext?e$B$,e(Bnile$B$rJV$9$s$G$9$,!"$3$l$O$"$se(B
e$B$^$j$&$l$7$/$J$$;EMMJQ99$G$9$M$(!#e(Bnext_pe$B$N<BAu$r$A$g$C$H9)IWe(B
e$B$9$l$P$h$$$N$+$7$i$s!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:31513] Re: nested fiber invocation”
on Mon, 20 Aug 2007 11:14:53 +0900, Yukihiro M.
[email protected] writes:

|e$B$"$H!"<B:]$KFI$_9~$`A0$Ne(Bnext?e$B$,e(Bnile$B$rJV$9$s$G$9$,!"$3$l$O$"$se(B
|e$B$^$j$&$l$7$/$J$$;EMMJQ99$G$9$M$(!#e(Bnext_pe$B$N<BAu$r$A$g$C$H9)IWe(B
|e$B$9$l$P$h$$$N$+$7$i$s!#e(B

  • next_pe$B$NCf$Ge(Be->fibe$B$,e([email protected]$C$?$ie(Bnext_inite$B$r8F$Ve(B
  • nexte$B$NCf$GNc30H/@8A0$Ke(Be->has_nexte$B$re(Bnile$B$Ke(B

e$B$7$F$_$^$7$?!#$I$&$b4|BTDL$jF0$$$F$$$k$h$&$G$9!#$7$+$7!"<B$Oe(B
e$B8e<T$OITMW$N$h$&$G$9!#e(B

[email protected]$G$9!#e(B

Yukihiro M. wrote:

e$B$$!"$A$c$s$HF0$/!#$G$b!"$I$&$7$F:#$^[email protected]$H%@%a$G!V%V%m%Ce(B
e$B%/$N:G8e$be(B rb_fiber_yield e$B$GLa$k!W$HBg>fIW$J$N$+$O$h$/$o$+$ie(B
e$B$J$$$s$G$9$1$I!#e(B

e$B!!5U$K!"%V%m%C%/$,$=$N$^$^=*N;$7$?$i$I$&$J$k$G$7$g$&!"$H$$$&OC$G$9!#e(B
e$B5$IU$/$N$N;~4V$,[email protected]$1$I!"1sF#$5$s$O:G=i$+$i$=$l$r;XE&$7$F$$e(B
e$B$k$H$$$&!#e(B

e$B!!$D$^$j!“e(BFiber
e$B$N%V%m%C%/$,=*N;$7$?$i$I$&$J$k$+!”$H$$$&OC$J$s$G$9e(B
e$B$,!#e(BFiber
e$B$N%V%m%C%/$,=*N;$7$?$i!“Nc30!”$C$D$&$N$,$$$$$h$&$J5$$,$7$Fe(B
e$B$$$^$9!#$G$O!“2?$KNc30$rEj$2$k$N$+$C$F$N$,$^$?LLE]$J$s$G$9$,!#$&!<e(B
e$B$s!”$I$&$7$h$&!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:31508] Re: nested fiber invocation”
on Sun, 19 Aug 2007 21:16:13 +0900, SASADA Koichi [email protected]
writes:

|e$B!!$3$s$J46$8$G$I$&$G$7$g$&!#$D$^$j!"%V%m%C%/$N:G8e$be(B rb_fiber_yield
|e$B$GLa$k$h$&$K$7$^$7$g$&$C$F46$8$G!#e(B

e$B%3%_%C%H$7$F$/[email protected]$5$$!#e(B

[email protected]$G$9!#e(B

Yukihiro M. wrote:

e$B%3%_%C%H$7$F$/[email protected]$5$$!#e(B

e$B!!$D$$$G$K%F%9%H$b%3%_%C%H$7$^$7$?!de(Btest/ruby/test_enumerator.rb

e$B!!;d$OF,$,0-$$$N$G!"$I$&$"$k$Y$-$+$9$0$KK:$l$F$7$^$$$^$9!#2?$+DI2C$7e(B
e$B$?$i%F%9%H$b$D$$$G$KDI2C$7$H$$$F$b$i$($k$H=u$+$j$^$9!#e(B

e$B!!:G6a!"EDCf$5$s$NCf$G$O%F%9%H%U%!!<%9%H!Je(BSEGVe$B$9$k%F%9%H$bFM$C9~$s$Ge(B
e$B$*$/!K$H$$$&$N$,N.9T$C$F$k$=$&$J$s$G$9$,!"[email protected]$9$k$N$rK:$l$Je(B
e$B$$!“NI$$<[email protected]$J$”$H;W$$$^$9!#e(B

[email protected]!“8D?ME*$K$O!“e(Bknown bug
e$B$G$”$k$3$H$,[email protected]$K$J$k$h$&$K!”%U%!%$%ke(B
e$B$rJ,$1$F$/$l$k$H$$$$$H;W$&[email protected]$1$I!J2r7h$7$?;[email protected]$GE,@Z$J%F%9%H%U%!%$e(B
e$B%k$X0\F0!K!#e(B

[email protected]$G$9!#e(B

e$B!!F,[email protected]}$N$?$a$K!"e(BRubye$B$G=q$$$F$_$^$7$?!#e(B

class Gen
def initialize e
@e = e
@fib = nil
end

def next?
init_next unless @fib
@has_next
end

def next
init_next unless @fib
raise “mou naiyo” unless @has_next
r = @next
@fib.yield(Fiber.current)
r
end

def rewind
@fib = nil
self
end

private
def init_next
@fib = Fiber.new{|fib|
@has_next = true
@e.each{|e|
@next = e
fib = fib.yield(e)
}
@has_next = false
fib.yield(nil)
}
@fib.yield(Fiber.current)
end
end

gen = Gen.new(3.times)
p gen.next
p gen.next
p gen.next
gen.rewind
p gen.next

e$B!!e(BFiber
e$BCf$GH/@8$7$?Nc30$r$I$3$KEAHB$5$;$k$N$+!"$d$C$Q$j$I$&$K$b$o$+e(B
e$B$i$J$$$N$G!"e(BSemiCoroutine e$B$H$7$F<[email protected]$m$&$+!#e(B