土岐です。

Date: Sun, 1 Aug 1999 08:36:48 +0900
Subject: [ruby-list:15809] Re: ERb について
Masatoshi SEKI <m_seki / mva.biglobe.ne.jp> wrote...

SEKI> このパッチで ERb もうまく動きました。
SEKI> 松尾さん、土岐さんの環境ではどうでしょうか?

わたしの環境でもうまく動きました。

Date: Sun, 1 Aug 1999 12:32:59 +0900
Subject: [ruby-list:15811] Re: ERb について
matsuo hisanori <matsuo_hisanori / pop21.odn.ne.jp> wrote...

matsuo> スレッドセーフにする為なんだろうけど、あそこでスレッドを使
matsuo> うには、どういう意味があるのかな…。

ERb の生成するスクリプトをスレッドで評価しているのは、もともとは $SAFE 
を変更するためだったようです。

Date: Sun, 1 Aug 1999 14:44:57 +0900
Subject: [ruby-list:15814] Re: ERb について
Masatoshi SEKI <m_seki / mva.biglobe.ne.jp> wrote...

SEKI> $SAFE を使わない時は、スレッドにしなくても良い気がしてきました。
SEKI> 実際、スレッドやめても動いているみたい。

わたしもそんな気がしてきました。ERb が呼ばれたスレッドは ERb の評価が
終了するまで動くことはないので、標準出力が ERb と衝突することはないか
ら、StringIO のからくりはうまく働きそうに思えます。でもそうすると今の
ままではスレッドが生きているあいだは DefOut に ERb の出力結果が残っちゃ
いますね。

あと 1.3 系だと StringIO#write に print の引数のオブジェクトがそのまま
渡されるみたいで、StringIO#write の中でオブジェクトを文字列に変換して
やらないといけないみたいです。IO の実装が変わったのかな。

SEKI> # あれ?? $SAFE=4 がうごかない…。1.3系だから!?

"Insecure: can't access instance variable" ですか。
これだとスクリプトではどうしようもないような気が...

それで、以上の点をふまえて strio.rb を修正してみました。
参考になれば幸いです。

*** strio.rb.orig	Sun Aug  1 17:09:29 1999
--- strio.rb	Sun Aug  1 18:43:06 1999
***************
*** 16,21 ****
--- 16,27 ----
      end
    end
  
+    def clear
+      @m.synchronize do
+        @writers.delete(Thread.current)
+      end
+    end
+ 
    def cleanup
      @m.synchronize do
        @writers.delete_if do |k, v|
***************
*** 23,29 ****
        end
      end
    end
!   module_function :write, :set, :cleanup
  
    @m = Mutex.new
    @writers = Hash.new
--- 29,35 ----
        end
      end
    end
!   module_function :write, :set, :clear, :cleanup
  
    @m = Mutex.new
    @writers = Hash.new
***************
*** 51,69 ****
    attr :str
  
    def write(str)
!     @str.concat(str)
    end
  
!   def as_stdout(safe=nil)
!     t = Thread.new {
!       out = StringIO.new
!       DefOut.set(out)
!       $SAFE = safe if safe
        yield
!       out.str
!     }
!     DefOut.cleanup
!     t.value
    end
    module_function :as_stdout
  end
--- 57,95 ----
    attr :str
  
    def write(str)
!     @str.concat(str.to_s)
    end
  
!   def _as_stdout
!     out = StringIO.new
!     DefOut.set(out)
!     begin
        yield
!     ensure
!       DefOut.clear
!     end
!     out.str
!   end
!   module_function :_as_stdout
! 
!   def as_stdout(safe=$SAFE)
!     if safe > $SAFE
!       _as_stdout do
! 	t = Thread.new {
! 	  $SAFE = safe
! 	  yield
! 	}
! 	begin
! 	  t.join		# for ruby-1.3
! 	rescue NameError
! 	  Thread.join t		# for ruby-1.2
! 	end
!       end
!     else
!       _as_stdout do
! 	yield
!       end
!     end
    end
    module_function :as_stdout
  end

----------------------------------------------------------------------
土岐 仁謙	神戸大学物理高エネ研 M2
URL: http://www3.phys.sci.kobe-u.ac.jp/~toki/index.html
PGP fingerprint = D0 A8 90 AB 73 F8 34 FE  CE CA DB BF 01 30 C0 35