From 239028e1739a0208b2ba383db4f11113cea3cbe8 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Fri, 10 Feb 2012 13:23:17 -0500 Subject: [PATCH] async: Use idle callbacks for UI updating Rather than explicit locking. One step closer to dropping thread locking. --- src/virtManager/asyncjob.py | 87 ++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/src/virtManager/asyncjob.py b/src/virtManager/asyncjob.py index e64bd84f1..9585358fc 100644 --- a/src/virtManager/asyncjob.py +++ b/src/virtManager/asyncjob.py @@ -128,6 +128,11 @@ def _simple_async(callback, args, title, text, parent, errorintro, parent.err.show_err(error, details=details) +def idle_wrapper(fn): + def wrapped(self, *args, **kwargs): + return self.safe_idle_add(fn, self, *args, **kwargs) + return wrapped + # Displays a progress bar while executing the "callback" method. class vmmAsyncJob(vmmGObjectUI): @@ -237,33 +242,12 @@ class vmmAsyncJob(vmmGObjectUI): self.widget("warning-box").show() self.widget("warning-text").set_markup(markup) - def exit_if_necessary(self, force_exit=False): - thread_active = (self.bg_thread.isAlive() or not self.async) - - if not thread_active or force_exit: - if self.async: - gtk.main_quit() - return False - - if not self.is_pulsing or not self.show_progress: - return True - - gtk.gdk.threads_enter() - try: - self.pbar.pulse() - finally: - gtk.gdk.threads_leave() - - return True - ########### # Actions # ########### def run(self): - # Don't use safe_timeout_add, since it's mostly needless locking - # since a lot of these windows don't touch any UI timer = gobject.timeout_add(100, self.exit_if_necessary) if self.show_progress: @@ -322,38 +306,41 @@ class vmmAsyncJob(vmmGObjectUI): # All functions after this point are called from the timer loop # which means we need to be careful and lock threads before doing # any UI bits + def exit_if_necessary(self, force_exit=False): + thread_active = (self.bg_thread.isAlive() or not self.async) + + if not thread_active or force_exit: + if self.async: + gtk.main_quit() + return False + + if not self.is_pulsing or not self.show_progress: + return True + + self.safe_idle_add(self.pbar.pulse) + return True + + @idle_wrapper def pulse_pbar(self, progress="", stage=None): - gtk.gdk.threads_enter() - try: - self.is_pulsing = True - self.pbar.set_text(progress) - self.set_stage_text(stage or _("Processing...")) - finally: - gtk.gdk.threads_leave() - + self.is_pulsing = True + self.pbar.set_text(progress) + self.set_stage_text(stage or _("Processing...")) + @idle_wrapper def set_pbar_fraction(self, frac, progress, stage=None): - gtk.gdk.threads_enter() - try: - self.is_pulsing = False - self.set_stage_text(stage or _("Processing...")) - self.pbar.set_text(progress) - - if frac > 1: - frac = 1.0 - if frac < 0: - frac = 0 - self.pbar.set_fraction(frac) - finally: - gtk.gdk.threads_leave() + self.is_pulsing = False + self.set_stage_text(stage or _("Processing...")) + self.pbar.set_text(progress) + if frac > 1: + frac = 1.0 + if frac < 0: + frac = 0 + self.pbar.set_fraction(frac) + @idle_wrapper def set_pbar_done(self, progress, stage=None): - gtk.gdk.threads_enter() - try: - self.is_pulsing = False - self.set_stage_text(stage or _("Completed")) - self.pbar.set_text(progress) - self.pbar.set_fraction(1) - finally: - gtk.gdk.threads_leave() + self.is_pulsing = False + self.set_stage_text(stage or _("Completed")) + self.pbar.set_text(progress) + self.pbar.set_fraction(1)