[#27919] 1.8.4 Preview2 検証 — "URABE Shyouhei aka. mput" <root@...>

卜部です。

33 messages 2005/12/01

[#27997] 1.8.4 documents? — "URABE Shyouhei aka. mput" <root@...>

卜部です。

22 messages 2005/12/12
[#28017] Re: 1.8.4 documents? — Koji Arai <jca02266@...> 2005/12/13

新井です。

[#28082] ruby_1_8 Segmentation fault on Cygwin — yanagi@...

柳田です。

13 messages 2005/12/21
[#28083] Re: ruby_1_8 Segmentation fault on Cygwin — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2005/12/21

山本です。

[#28140] ia64-hpux11.23/socket.sl: this executable file can't load extension libraries (LoadError) — Tanaka Akira <akr@...17n.org>

HP-UX で HP aC++/ANSI C を使って作った ruby で、openssl や drb のテストをすると、

34 messages 2005/12/27
[#28141] Re: ia64-hpux11.23/socket.sl: this executable file can't load extension libraries (LoadError) — WATANABE Tetsuya <Tetsuya.WATANABE@...> 2005/12/28

渡辺哲也です。

[#28142] Re: ia64-hpux11.23/socket.sl: this executable file can't load extension libraries (LoadError) — Tanaka Akira <akr@...17n.org> 2005/12/28

In article <200512280307.jBS37nnj005909@pbsg500.nifty.com>,

[#28147] Re: ia64-hpux11.23/socket.sl: this executable file can't load extension libraries (LoadError) — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2005/12/28

山本です。

[#28149] Re: ia64-hpux11.23/socket.sl: this executable file can't load extension libraries (LoadError) — Tanaka Akira <akr@...17n.org> 2005/12/28

In article <20051228210640.13C71A10.ocean@m2.ccsnet.ne.jp>,

[#28151] Re: ia64-hpux11.23/socket.sl: this executable file can't load extension libraries (LoadError) — WATANABE Tetsuya <Tetsuya.WATANABE@...> 2005/12/29

渡辺哲也です。

[#28152] Re: ia64-hpux11.23/socket.sl: this executable file can't load extensionlibraries (LoadError) — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2005/12/29

山本です。

[#28153] Re: ia64-hpux11.23/socket.sl: this executable file can't load extensionlibraries (LoadError) — "H.Yamamoto" <ocean@...2.ccsnet.ne.jp> 2005/12/29

山本です。

[#28154] thread based generator.rb — Tanaka Akira <akr@...17n.org> 2005/12/29

In article <20051229114438.44D19F00.ocean@m2.ccsnet.ne.jp>,

[ruby-dev:28157] Re: thread based generator.rb

From: "H.Yamamoto" <ocean@...2.ccsnet.ne.jp>
Date: 2005-12-29 04:41:00 UTC
List: ruby-dev #28157
山本です。

>> http://rubyforge.org/tracker/index.php?func=detail&aid=1364&group_id=426&atid=1698 を閉じようと
>> 思って試したら、まだメモリリークしますね。--;;
>>
>> よく考えると Thread は参照が切れても生きつづけるので、Generator の参照が切れたときに Thread も
>> 終了させないと駄目なのか・・・もう少し考えてみます。
>
>おぉ、それは気がついていませんでした。
>
>ふむ。ちょっとした思い付きですが、他のスレッドから操作されな
>い限り動き出さない thread は GC の root にしない、というアイ
>デアはどうでしょう?

こちらはインタプリタの話になるので私にはわかりませんが、
ファイナライザでどうにかできないかといじってみた結果、それらしく動くように
なりました。(まだ適当なコードで、コミットできる状態ではありません)

ただ、

require 'generator'

while true
  g = Generator.new { yield 1 }
  GC.start
#  p Thread.list
#  sleep 1
end

でいずれかのコメントを外すとメモリリークしなくなるのですが、
何もウェイトのない状態だと、メモリ使用量がどんどん増えていきます。
ファイナライザで @loop_thread.join してみましたが変わりません。

また、以前スコープの話がありましたが、

    g = Generator.new { |g2|
      for i in 'A'..'C'
        g2.yield i
      end

      g2.yield 'Z'
    }

というように変えないと、ブロック引数の g が外部に渡ってしまうのは
やっぱり違和感を覚えます。(g2 よりも g に代入されるのが後だけに)

Index: generator.rb
===================================================================
RCS file: /src/ruby/lib/generator.rb,v
retrieving revision 1.5
diff -u -w -b -p -r1.5 generator.rb
--- generator.rb	29 Dec 2005 02:29:26 -0000	1.5
+++ generator.rb	29 Dec 2005 04:26:30 -0000
@@ -56,16 +56,11 @@
 class Generator
   include Enumerable
 
-  # Creates a new generator either from an Enumerable object or from a
-  # block.
-  #
-  # In the former, block is ignored even if given.
-  #
-  # In the latter, the given block is called with the generator
-  # itself, and expected to call the +yield+ method for each element.
+  class GeneratorProxy
+
   def initialize(enum = nil, &block)
     if enum
-      @block = proc{|g| enum.each{|value| g.yield value}}
+	      @block = proc{|proxy| enum.each{|value| proxy.yield value}}
     else
       @block = block
     end
@@ -83,10 +78,8 @@ class Generator
         Thread.critical = false
       end
     end
-    self
   end
 
-  # Yields an element to the generator.
   def yield(value)
     if Thread.current != @loop_thread
       raise RuntimeError.new("Generator#yield must be called in Generator.new{|g| ... }")
@@ -95,10 +88,8 @@ class Generator
     @main_thread.wakeup
     Thread.stop
     Thread.critical = true
-    self
   end
 
-  # Returns true if the generator has reached the end.
   def end?
     if @queue.empty?
       Thread.critical = true
@@ -116,37 +107,83 @@ class Generator
     @queue.empty?
   end
 
+		def index
+			@index
+		end
+
+		def next
+	    raise EOFError.new("no more elements available") if end?
+	    @index += 1
+	    @queue.shift
+		end
+
+	  def current
+	    raise EOFError.new("no more elements available") if end?
+	    @queue.first
+	  end
+
+		def rewind
+	    initialize(nil, &@block) if @index.nonzero?
+		end
+
+    def create_finalizer
+      proc { @loop_thread.kill; @loop_thread.join }
+    end
+
+  end
+
+  # Creates a new generator either from an Enumerable object or from a
+  # block.
+  #
+  # In the former, block is ignored even if given.
+  #
+  # In the latter, the given block is called with the generator
+  # itself, and expected to call the +yield+ method for each element.
+  def initialize(enum = nil, &block)
+    @proxy = GeneratorProxy.new(enum, &block)
+    ObjectSpace.define_finalizer(self, @proxy.create_finalizer)
+    self
+  end
+
+  # Yields an element to the generator.
+  def yield(value)
+    @proxy.yield(value)
+    self
+  end
+
+  # Returns true if the generator has reached the end.
+  def end?
+    @proxy.end?
+  end
+
   # Returns true if the generator has not reached the end yet.
   def next?
-    !end?
+    !@proxy.end?
   end
 
   # Returns the current index (position) counting from zero.
   def index
-    @index
+    @proxy.index
   end
 
   # Returns the current index (position) counting from zero.
   def pos
-    @index
+    @proxy.index
   end
 
   # Returns the element at the current position and moves forward.
   def next
-    raise EOFError.new("no more elements available") if end?
-    @index += 1
-    @queue.shift
+		@proxy.next
   end
 
   # Returns the element at the current position.
   def current
-    raise EOFError.new("no more elements available") if end?
-    @queue.first
+  	@proxy.current
   end
 
   # Rewinds the generator.
   def rewind
-    initialize(nil, &@block) if @index.nonzero?
+		@proxy.rewind
     self
   end
 
@@ -251,12 +288,12 @@ class TC_Generator < Test::Unit::TestCas
   end
 
   def test_block2
-    g = Generator.new { |g|
+    g = Generator.new { |g2|
       for i in 'A'..'C'
-        g.yield i
+        g2.yield i
       end
 
-      g.yield 'Z'
+      g2.yield 'Z'
     }
 
     assert_equal(0, g.pos)


In This Thread