From 74bed91d957626ec16438f134319218d53a481b7 Mon Sep 17 00:00:00 2001 From: Lars Kanis <kanis@comcard.de> Date: Fri, 26 Jun 2015 09:58:47 +0200 Subject: [PATCH] Add runOnUiThread to FXApp and FXId. This allows to safely execute GUI code from other threads. --- lib/fox16.rb | 1 + lib/fox16/thread.rb | 50 +++++++++++++++++++++++++++++++++++++++++++ rdoc-sources/FXApp.rb | 5 +++++ rdoc-sources/FXId.rb | 5 +++++ test/TC_FXApp.rb | 35 ++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 lib/fox16/thread.rb diff --git a/lib/fox16.rb b/lib/fox16.rb index 7902976..bfe60ea 100644 --- a/lib/fox16.rb +++ b/lib/fox16.rb @@ -28,3 +28,4 @@ require "fox16/execute_nonmodal" require "fox16/version" require "fox16/kwargs" require "fox16/exceptions_for_fxerror" +require "fox16/thread" diff --git a/lib/fox16/thread.rb b/lib/fox16/thread.rb new file mode 100644 index 0000000..0cf58ee --- /dev/null +++ b/lib/fox16/thread.rb @@ -0,0 +1,50 @@ +require 'thread' + +module Fox + + class FXApp + + alias initialize_before_thread initialize # :nodoc: + + def initialize(*args, &block) + initialize_before_thread(*args, &block) + event_handler_setup + end + + def runOnUiThread(&block) + @event_handler_events << block + @event_handler_pwr.write 'e' if @event_handler_pwr + end + + private + + def event_handler_setup + if RUBY_PLATFORM =~ /mingw|mswin/i + require 'socket' + gs = TCPServer.open('localhost', 0) + prd = TCPSocket.open('localhost', gs.addr[1]) + pwr = gs.accept + else + prd, pwr = IO.pipe + end + self.addInput(prd, Fox::INPUT_READ){ event_handler_pull(prd) } + @event_handler_pwr = pwr + @event_handler_events = Queue.new + end + + def event_handler_pull(prd) + prd.read(1) if prd + while !@event_handler_events.empty? + ev = @event_handler_events.shift + ev.call + end + end + + end # class FXApp + + class FXId + def runOnUiThread(&block) + app.runOnUiThread(&block) + end + end +end # module Fox diff --git a/rdoc-sources/FXApp.rb b/rdoc-sources/FXApp.rb index d21b7f3..3e533be 100755 --- a/rdoc-sources/FXApp.rb +++ b/rdoc-sources/FXApp.rb @@ -538,5 +538,10 @@ module Fox # Check to see if multithreaded applications are supported def threadsEnabled?(); end + + # Runs the specified block on the UI thread. + # + # The block is posted to the event queue of the UI thread. + def runOnUiThread(&block); end end end diff --git a/rdoc-sources/FXId.rb b/rdoc-sources/FXId.rb index 664c4f9..cbef725 100755 --- a/rdoc-sources/FXId.rb +++ b/rdoc-sources/FXId.rb @@ -30,5 +30,10 @@ module Fox # Destroy resource. # def destroy(); end + + # Runs the specified block on the UI thread. + # + # The block is posted to the event queue of the UI thread. + def runOnUiThread(&block); end end end diff --git a/test/TC_FXApp.rb b/test/TC_FXApp.rb index 1ebef42..c870993 100755 --- a/test/TC_FXApp.rb +++ b/test/TC_FXApp.rb @@ -81,4 +81,39 @@ class TC_FXApp2 < Fox::TestCase pipe_rdwr = IO.popen("cat", "r+") check_events pipe_rdwr, pipe_rdwr end + + def test_runOnUiThread + count = 0 + thread = nil + Thread.new do + 10.times do |idx| + app.runOnUiThread do + count += 1 + thread = Thread.current + app.stop if idx == 9 + end + sleep 0.001 + end + end + app.run + + assert_equal Thread.current, thread + assert_equal 10, count + end + + def test_runOnUiThread_same_thread + count = 0 + app.addTimeout(1) do + 10.times do |idx| + app.runOnUiThread do + count += 1 + app.stop if idx == 9 + end + sleep 0.001 + end + end + app.run + + assert_equal 10, count + end end -- GitLab