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