[Kde-bindings] Using threads with QtRuby
Uriel
uriel at inbox.ru
Fri Feb 5 19:37:16 UTC 2010
> But you only get a log of vitual method callbacks if you want them.
> The are
> various levels and types of debug output and it is quite easy to
> customize.
> Maybe it is a bit over complicated but you will only get virtual method
> callbacks logged if one of the things you pass to
> Qt::Internal.setDebug() is
> QTDB_VIRTUAL.
Yes, I know about different debug levels, thank you. But sometimes I
become paranoid and explicitly set level to QTDB_ALL complicating all
the thing around myself. :) So, may be it's not a really big deal.
Here is the small patch for qtruby4.rb in trunk with comments. I've
tested it on different amount of threads and everything seems to be ok.
--- qtruby4.rb 2010-02-06 00:20:35.056527428 +0500
+++ qtruby4.rb 2010-02-06 00:31:59.293534007 +0500
@@ -43,6 +43,17 @@
@@debug_level
end
+ # We're causing main thread to sleep for some really small amount
of time time to force Ruby VM do the scheduling
+ @@ruby_thread_sleep_time = 1e-9
+
+ def Qt.ruby_thread_sleep_time
+ @@ruby_thread_sleep_time
+ end
+
+ def Qt.ruby_thread_sleep_time=(time)
+ @@ruby_thread_sleep_time = time
+ end
+
module Internal
#
# From the enum MethodFlags in qt-copy/src/tools/moc/generator.cpp
@@ -454,6 +465,26 @@
end
class Application < Qt::Base
+ private
+ def enable_ruby_threads
+ # Start timer if only it hasn't been started yet
+ return unless @ruby_threads_timer_id == -1
+
+ @ruby_threads_timer_id = startTimer 0
+ end
+
+ def disable_ruby_threads
+ # Stop timer only if we have main thread and just one custom
which will be stopped right after this call
+ return unless Thread.list.count == 2
+
+ killTimer @ruby_threads_timer_id
+ @ruby_threads_timer_id = -1
+ end
+ protected
+ def timerEvent(ev)
+ sleep Qt::ruby_thread_sleep_time
+ end
+ public
def initialize(*args)
if args.length == 1 && args[0].kind_of?(Array)
super(args.length + 1, [$0] + args[0])
@@ -466,6 +497,8 @@
# Otherwise, rb_gc_call_finalizer_at_exit() can delete
# stuff that Qt::Application still needs for its cleanup.
def exec
+ @ruby_threads_timer_id = -1
+
method_missing(:exec)
self.dispose
Qt::Internal.application_terminated = true
@@ -3149,4 +3182,32 @@
end
end
+# We're doing some trick here by redefining all the methods for new
thread creation.
+# Then we adding custom function call to the user's block passed to one
of these functions.
+class Thread
+ class << self
+ alias :__oldNew :new
+ alias :__oldStart :start
+ alias :__oldFork :fork
+ end
+
+ def self.decorate_thread(old_method, *args, &block)
+ Qt::Application.instance.send :enable_ruby_threads
+ send old_method, *args, &proc{ block.call;
Qt::Application.instance.send :disable_ruby_threads }
+ end
+ private_class_method(:decorate_thread)
+
+ def self.new(*args, &block)
+ decorate_thread :__oldNew, *args, &block
+ end
+
+ def self.start(*args, &block)
+ decorate_thread :__oldStart, *args, &block
+ end
+
+ def self.fork(*args, &block)
+ decorate_thread :__oldFork, *args, &block
+ end
+end
+
# kate: space-indent false;
More information about the Kde-bindings
mailing list