[前][次][番号順一覧][スレッド一覧][生データ]

yarv-dev:426

From: SASADA Koichi <ko1 atdot.net>
Date: Wed, 23 Feb 2005 14:53:35 +0900
Subject: [yarv-dev:426] Re: special local variables

  Nobuyoshi Nakada <nobu.nokada softhome.net> wrote :
    [ [yarv-dev:411] Re: special local variables ]
    at Sun, 30 Jan 2005 10:28:57 +0900

 ささだです。
 遅くなりました。

>> 	def getproc
>> 	  /abc/ =~ 'abc'
>> 	  $pr = proc{
>> 	    p $~
>> 	  }
>> 	  proc{
>> 	    /123/ =~ '123'
>> 	  }
>> 	end
>> 
>> 	pr1 = getproc
>> 	pr2 = proc{
>> 	  /123/ =~ '123'
>> 	  p $~
>> 	}
>> 
>> 
>> 	Thread.new{
>> 	  $pr.call
>> 	  pr1.call
>> 	  $pr.call
>> 	  p $~
>> 	  pr2.call
>> 	  p $~
>> 	}.join
>> 	#=>
>> 	#<MatchData:0x2ac66b8> # 他スレッドで作成した $~ が見れる
>> 	#<MatchData:0x2ac6550> # 自スレッドで作成した $~ が見れる
>> 	nil
>> 	#<MatchData:0x2ac64c0> 
>> 	nil # なんでだろー?   # 自スレッドで作成した $~ が見れない
> 
> どれもThread.mainで作成されたMatchDataです。Procが保持するコン
> テキストにはスレッドも含まれるので、pr2.callで作られた$~は元の
> スレッドとは異なる呼び出し元のスレッドからは見えない、というこ
> とです。

 なんとなくわかりました。以下、$~、$_ などの変数を svar と
呼ぶことにします。こんな規則でしょうか。

1. svar はメソッド(クラス)スコープローカルであり、
   ブロック(スコープ)ローカルではない

2. svar はスレッドローカルである

3. Proc オブジェクト中でアクセスする svar はその Proc を作成した
   スレッドにローカルである


 svar の位置をメソッド(クラス)ローカル変数領域に置いたと
き、注意しなければいけないのは新しいスレッドを生成したとき、
その Proc(ブロック)からみえる svar へアクセスしてはいけな
い、ということだけなのですね。

	pr = lambda{
	  $~ # これが参照数のは常に Thread.main の $~
	     # 呼び出し元が他のスレッドでも関係ない
	}

	Thread.new{
	  $~ # この svar は Thread.main の $~ では無い
	}

 というわけで、YARV ではもしその svar の位置がスレッドの
ルートだったら別の記憶領域(Thread オブジェクトだけが保持)
を参照することにします。

 しかし、そうすると、ある Proc を複数のスレッドで並行に実行
した場合、$~ の値は突然変わってしまう可能性があるんですね。


 と思って、以下のスクリプトを動かしたんですが、どうも違うよ
うです。

	p1 = lambda{|str|
	  /(\d+)/ =~ str
	}

	Thread.new{
	  loop{
	    p1.call("".__id__.to_s)
	    Thread.pass
	  }
	}

	loop{
	  p $1                            #=> nil ばっかり
	  Thread.pass
	}


 しかし、こっちだと予想通りうまくいきました。

	def m
	  $p1 = lambda{|str|
	    /(\d+)/ =~ str
	  }
	  $p2 = lambda{
	    p $1
	  }
	end

	m

	Thread.new{
	  loop{
	    $p1.call("".__id__.to_s)
	    Thread.pass
	  }
	}

	loop{
	  $p2.call                        #=> id を沢山表示
	  Thread.pass
	}


 現状の挙動は、実装上の都合って感じですかね。トップレベルも
含め、後者の挙動にしようと思うんですが、いいでしょうか。


-- 
// SASADA Koichi at atdot dot net
//

--
ML: yarv-dev quickml.atdot.net
使い方: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]

       409 2005-01-25 17:28 [ko1 atdot.net       ] special local variables                 
       410 2005-01-25 17:42 ┣[matz ruby-lang.org  ]                                       
       411 2005-01-30 10:28 ┗[nobu.nokada softhome]                                       
->     426 2005-02-23 14:53  ┗[ko1 atdot.net       ]                                     
       455 2005-03-09 09:25   ┗[matz ruby-lang.org  ]