Forums | Admin

Discussion Forums: help

Start New Thread Start New Thread

 

By: Yonatan Elhanan
My helper classes for background threads [ reply ]  
2010-05-08 08:21
Hi,

It's pretty late to post such helpers, because ruby 1.9 with its native threads will eliminates the need for emulation, but right now ruby 1.8.6 installer is the best option for windows developers, and so we have to emulate threads with Qt QTimer.

My classes ran through several iterations and in each I found bugs pretty much accidentally. I'd like the experienced developers to take a look and see if they find potential bugs or optimizations.

It's pretty basic and maybe later as my project evolves I'll have to add thread pause/resume etc.

It doesn't support threads within threads. Only basic background worker that can send gui updates to the gui's event queue.

#Usage:
@worker = Utils::Qt::Worker.new {
#...long computation
Utils::Qt::Tasks.invokeLater {
#update GUI
}
#...another long computation
}

#... Inside a clearForm slot:
@worker.kill if !@worker.nil?
Utils::Qt::Tasks.flush #Call pending GUI tasks
#...clear all widgets


# EventQueueRepetition.rb
module Utils end

module Utils::Qt
class EventQueueRepetition
def self.startNew(&block)
new(&block).qtImplementor
end

attr_reader :qtImplementor

def initialize(once = false, &block)
@qtImplementor = QtImplementor.new(once, block)
end

class QtImplementor < Qt::Object
slots 'runAsEvent()'
def runAsEvent()
@block.call(self)
Thread.pass
end

def stop
@timer.stop
end

def initialize(once, block)
super()
@block = block
@timer = Qt::Timer.new()
@timer.interval = 5
@timer.singleShot = once
connect(@timer, SIGNAL('timeout()'), self, SLOT('runAsEvent()'))
@timer.start
end
end
end
end


# Worker.rb
require File.join(File.dirname(__FILE__), 'EventQueueRepetition')

module Utils
end

module Utils::Qt
class Worker
@@workers = Array.new

def initialize
super()
@rubyThread = Thread.new {yield}
@@workers << self
@repetition = EventQueueRepetition.startNew {|repetition|
if !@rubyThread.nil? and !@rubyThread.alive?
repetition.stop
@@workers.delete(self)
end
}
end

def kill
@rubyThread.kill
end
end
end


# Tasks.rb
require 'singleton'
require File.join(File.dirname(__FILE__), 'EventQueueRepetition')

module Utils end

module Utils::Qt
class Tasks
include Singleton

def initialize
@tasks = Queue.new
@tasksLock = Mutex.new
@repetition = EventQueueRepetition.startNew {
flush
}
end

def invokeLater(&block)
@tasksLock.synchronize {
@tasks << block
}
end

def flush
@tasksLock.synchronize {
while !@tasks.empty?
@tasks.pop.call
end
}
end

def self.invokeLater(&block)
instance.invokeLater(&block)
end

def self.flush
instance.flush
end
end
end