summaryrefslogtreecommitdiff
path: root/ext/tk/lib/multi-tk.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tk/lib/multi-tk.rb')
-rw-r--r--ext/tk/lib/multi-tk.rb65
1 files changed, 53 insertions, 12 deletions
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index c491d0c7ba..dc8a31e2e8 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -118,6 +118,27 @@ MultiTkIp_OK.freeze
################################################
# methods for construction
class MultiTkIp
+ class Command_Queue < Queue
+ def initialize(interp)
+ @interp = interp
+ super()
+ end
+
+ def push(value)
+ if !@interp || @interp.deleted?
+ fail RuntimeError, "Tk interpreter is already deleted"
+ end
+ super(value)
+ end
+ alias << push
+ alias enq push
+
+ def close
+ @interp = nil
+ end
+ end
+ Command_Queue.freeze
+
BASE_DIR = File.dirname(__FILE__)
WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class
@@ -692,15 +713,29 @@ class MultiTkIp
begin
loop do
sleep 1
- receiver.kill if @interp.deleted?
+ if @interp.deleted?
+ receiver.kill
+ @cmd_queue.close
+ end
break unless receiver.alive?
end
rescue Exception
# ignore all kind of Exception
end
+
# receiver is dead
+ retry_count = 3
loop do
- thread, cmd, *args = @cmd_queue.deq
+ Thread.pass
+ begin
+ thread, cmd, *args = @cmd_queue.deq(true) # non-block
+ rescue ThreadError
+ # queue is empty
+ retry_count -= 1
+ break if retry_count <= 0
+ sleep 0.5
+ retry
+ end
next unless thread
if thread.alive?
if @interp.deleted?
@@ -838,7 +873,7 @@ class MultiTkIp
@safe_level = [$SAFE]
- @cmd_queue = Queue.new
+ @cmd_queue = MultiTkIp::Command_Queue.new(@interp)
@cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])
@@ -1228,6 +1263,7 @@ class MultiTkIp
@slave_ip_top[ip_name] = top_path
end
@interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}")
+ @interp._invoke('__replace_slave_tk_commands__', ip_name)
else
@slave_ip_top[ip_name] = nil
end
@@ -1259,6 +1295,7 @@ class MultiTkIp
slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String)
slave_ip._invoke('set', 'argv', _keys2opts(keys))
@interp._invoke('load', '', 'Tk', ip_name)
+ @interp._invoke('__replace_slave_tk_commands__', ip_name)
@slave_ip_tbl[ip_name] = slave_ip
[slave_ip, ip_name]
end
@@ -1373,16 +1410,20 @@ class MultiTkIp
current[:status] = status
begin
- current[:status].value = interp.mainloop(true)
- rescue SystemExit=>e
- current[:status].value = e
- rescue Exception=>e
- current[:status].value = e
- retry if interp.has_mainwindow?
+ begin
+ current[:status].value = interp.mainloop(true)
+ rescue SystemExit=>e
+ current[:status].value = e
+ rescue Exception=>e
+ current[:status].value = e
+ retry if interp.has_mainwindow?
+ ensure
+ mutex.synchronize{ cond_var.broadcast }
+ end
+ current[:status].value = interp.mainloop(false)
ensure
- mutex.synchronize{ cond_var.broadcast }
+ interp.delete
end
- current[:status].value = interp.mainloop(false)
}
until @interp_thread[:interp]
Thread.pass
@@ -1456,7 +1497,7 @@ class MultiTkIp
@pseudo_toplevel = [false, nil]
- @cmd_queue = Queue.new
+ @cmd_queue = MultiTkIp::Command_Queue.new(@interp)
=begin
@cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0])