Some answers - but not all... "Ara.T.Howard" <ahoward / fattire.ngdc.noaa.gov> schrieb im Newsbeitrag news:Pine.LNX.4.44.0402250704100.30572-100000 / fattire.ngdc.noaa.gov... > On Wed, 25 Feb 2004, Robert Klemme wrote: > > > "Ara.T.Howard" <Ara.T.Howard / noaa.gov> schrieb im Newsbeitrag > > news:Pine.LNX.4.44.0402242241480.28543-100000 / fattire.ngdc.noaa.gov... > > > > > > this program does not work as expected w/o inserting the > > 'Thread.critical' > > > bits - i must say i do not understand why, can someone help me > > understand? > > > > > > require 'tk' > > > require 'open3' > > > require 'io/nonblock' > > > $VERBOSE=nil > > > > > > r=TkRoot.new > > > l=TkLabel.new r, :text=>`ruby -e "p Time.now"` > > > l.pack > > > > > > command='ruby -e "loop{p Time.now; sleep 1}"' > > > i,o,e = Open3::popen3 command > > > i.close > > > text = nil > > > > > > Thread.new do > > > loop do > > > rios, = select [o,e], nil, nil > > > rios.map do |rio| > > > > Why do you use map here? Apparently you don't access the result of > > mapping so each would be more appropriate. > > right you are - in the actual code i do - this is a distilled example... Ah! > > > > > next if rio.eof? > > > Thread.critical = true # blocks w/o this > > > rio.nonblock{ text = rio.read } > > > Thread.critical = false # blocks w/o this > > > l.configure :text=>text > > > end > > > end > > > end > > > > > > Tk.mainloop > > > > > > > > > is this an o.k. technique to prevent a non-blocking read not to hand a > > > multi-threaded ap? > > > > > I'm not really sure I understand correctly what you're after. Could you > > elaborate that? > > a) why is the critical section needed to prevent one thread blocking the > entire process? That's an interesting question. One would rather expect "Thread.critical=true" to block the whole process. I guess, that there are no thread context changes without these methods and assigning to Thread.critical has the side effect of doing a context switch if possible. I'd try to use "Thread.pass" after "l.configure..." instead of "Thread.critical" to give other threads a chance to run and see what happens. > b) is this approach (critical section) the correct way of dealing with this > issue? If the blocking is indeed caused by the loop spinning endlessly, Thread.pass is a far better alternative. You could as well use sleep to achieve the same. > more fundmenetally WHY does using 'nonblock/read' block a thread when other io > ops, 'gets' for example do not? WHAT is the relationship between ioctl ops > and Thread.critical? That I don't know, maybe Matz or Nobu can comment on that. > > Generally speaking there's one piece of advice: > > > > When using Thread.critical= it is always best to do reset the flag in an > > ensure clause to make sure that the reset occurs under all conditions: > > > > Thread.critical = true > > begin > > # do stuff > > ensure > > Thread.critical = false > > end > > yes of course - i've always wondered why that one doesn't take a block... I guess because normally it's not intended for use in the open range. Normally one would use higher level constructs such as Mutex, Queue etc. Regards robert