原です。
In message "[ruby-list:15010] Thread safe eRuby"
on 99/06/16, Masatoshi SEKI <m_seki / mva.biglobe.ne.jp> writes:
|咳です。
|やや スレッドセーフ になった erb.rb
今ごろになって erb.rb がスレッドセーフとはどういう意味か理解しま
した。(^^;;;
erb.rb は同時に複数のスクリプトを評価して結果の標準出力を別々に得
る必要があるんですね。
|このバージョンでは、eRuby スクリプトがマルチスレッドなとき、
|ERb#result は正しく動作しません。
|eRubyスクリプトが単一のスレッドであれば、マルチスレッドから
|ERb を使っても期待通りに動いてくれると思います。
この仕様で十分な気がします。CGI みたいなスクリプトがマルチスレッ
ドで動いてそれぞれが出力を出すって事あります?基本的に HTTP って
1セッション内で対話しないから、いいんじゃないかなあ。
でも一応考えてみました。Thread.start の定義をいじるという大げさ
なものなんですけど、一応動いている様な気がします。
-----^ as_output.rb
class IO; alias write_orig write; end
class Thread; OUTPUTS = {}; end
class << Thread
alias start_orig start
def as_output(x)
if Thread::OUTPUTS.empty?
Thread.critical = true
def $stdout.write(s)
if io = Thread::OUTPUTS[Thread.current]
io.write(s)
else
write_orig(s)
end
end
def Thread.start(x = nil)
c = Thread.current
Thread.start_orig {
d = Thread.current
Thread::OUTPUTS[d] = x || Thread::OUTPUTS[c]
yield
Thread::OUTPUTS.delete d
if Thread::OUTPUTS.empty?
def $stdout.write(s); $stdout.write_orig(s); end
def Thread.start; Thread.start_orig {yield}; end
end
}
end
Thread.critical = false
end
Thread.start(x) {
yield
}.value
end
end
-----$ as_output.rb
テストプログラムです。
-----^ test.rb
#!/usr/local/bin/ruby
require "as_output"
Thread.abort_on_exception = true
def display(n=0)
(0..5).each { |i| puts i+n; Thread.pass}
end
class String
def write(x); concat(x); end
end
s1 = ""
s2 = ""
s3 = ""
thrs = []
thrs << Thread.start {
Thread.as_output(s1) {
thrs << Thread.start {
thrs << Thread.start {
display(1000)
}
display(1100)
}
}
}
puts "HELLO!"
Thread.as_output(s2) {
Thread.as_output(s3) {
thrs << Thread.start {
display(3100)
}
display(3000)
}
thrs << Thread.start {
display(2000)
}
Thread.as_output(s2) {
display(2100)
}
}
thrs.each do |x|
#Thread.join(x)
x.join
end
puts "----- s1 ------"
puts s1
puts "----- s2 ------"
puts s2
puts "----- s3 ------"
puts s3
-----$ test.rb