Gtk and Ruby threading issues
November 22nd 2008
In one of my classes, we are using Ruby and Gtk, but some issues have popped up. The most obvious is using a block to do GUI update stuff and the like, from another thread. Things die. Puppies are killed.
I found this post on Ruby Forum which fixed the problem.
Relevant code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | require "thread" module Gtk # Thread-safety stuff. # Loosely based on booh, by Guillaume Cottenceau. PENDING_CALLS_MUTEX = Mutex.new PENDING_CALLS = [] def self.thread_protect(&proc) if Thread.current == Thread.main proc.call else PENDING_CALLS_MUTEX.synchronize do PENDING_CALLS << proc end end end def self.thread_flush if PENDING_CALLS_MUTEX.try_lock for closure in PENDING_CALLS closure.call end PENDING_CALLS.clear PENDING_CALLS_MUTEX.unlock end end def self.init_thread_protect Gtk.timeout_add(100) do PENDING_CALLS_MUTEX.synchronize do for closure in PENDING_CALLS closure.call end PENDING_CALLS.clear end true end end end |
Basically, you call the Gtk.init_thread_protect method first when you start things up, then, whenever you need to do GUI update stuff, just wrap it in a Gtk.thread_protect {} block. Voila. It works. No more crashes. In looking at this code again now, some things could be made more Rubyesque, but we’ll go with it.
My version with minor changes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | require "thread" module Gtk PENDING_CALLS_MUTEX = Mutex.new PENDING_CALLS = [] def self.thread_protect(&proc) if Thread.current == Thread.main proc.call else PENDING_CALLS_MUTEX.synchronize do PENDING_CALLS << proc end end end def self.thread_flush if PENDING_CALLS_MUTEX.try_lock PENDING_CALLS.each { |closure| closure.call } PENDING_CALLS.clear PENDING_CALLS_MUTEX.unlock end end def self.init_thread_protect Gtk.timeout_add(100) do PENDING_CALLS_MUTEX.synchronize do PENDING_CALLS.each { |closure| closure.call } PENDING_CALLS.clear end true end end end |


