following is a simulation of a rather complex gui i’m working on. the gui
run a procedure which, itself, is communication with many other processes via
Open3::popen3 (i need the stderr)… anyhow, i’m having fits getting the gui
to update and do all the io (select/read, etc). this code seems to work fine
but i am very conerned that something might bite me later… if anyone would
care to comment on the interactions between the io and threads and if this is
a reccomended approach i’d love to hear it… remember this code might look a
bit funny but it demonstrative of what my code actually does. thanks in
advance for any help/advice
==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
require ‘tk’
require ‘open3’
require ‘io/wait’
require ‘io/nonblock’
require ‘thread’
$VERBOSE=nil
STDOUT.sync = STDERR.sync = true
Thread.abort_on_exception = true
threads =
#setup gui
root = TkRoot.new
label_a=TkLabel.new root, :text=>‘label_a’
label_b=TkLabel.new root, :text=>‘label_b’
label_a.pack
label_b.pack
start the gui running
threads <<
Thread.new{ Tk.mainloop }
simulation of my processing loop - which is communcating with another
process and updating a widget with it’s output
def update label, program
command=“ruby -e ‘#{ program }’”
i,o,e = Open3::popen3 command
i.close
we run in a thread so entire process is not blocked on io
we DO need to wait for it to complete though, because in the real code i
depend on values which are returned…
Thread.new do
o_done = false
e_done = false
loop do
rios, = select [o, e], nil, nil
rios.map do |rio|
break if o_done and e_done
if rio.eof?
rio == o ? o_done = true : e_done = true
next
end
# i like this better, but it hangs
# putting a critical section results in deadlock
# a semaphore is too slow…
#rio.nonblock{ text = rio.read }
# less elegant but works...
text = ''
sleep(0.42) and Thread.pass until rio.ready?
text << rio.getc while rio.ready?
label.configure :text=>text
end
end
end.join
end
start background processing which will update the labels
threads <<
Thread.new{
update label_a, ‘4.times{p Time.now; sleep 1}’
}
threads <<
Thread.new{
update label_b, ‘4.times{|i| p “foobar_#{ i }”; sleep 1}’
}
wait for everyone to finish
#threads.map{|t| t.join}
sleep
==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
-a
···
–
EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
URL :: Solar-Terrestrial Physics Data | NCEI
TRY :: for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done
===============================================================================