[PATCH 1/2] Add function to map functions on items in the main thread

Brian C. Lane bcl at redhat.com
Tue Nov 12 16:48:33 UTC 2013


On Sat, Nov 09, 2013 at 03:27:36PM +0100, Vratislav Podzimek wrote:
> Sometimes we need to map a function on a bunch of items in way that it is called
> in the main thread. And sometimes we also need to do some transformations on the
> items before we do the actions that need to take place in the main thread.
> 
> This patch adds a versatile function to do those actions in a probably best
> possible way.
> 
> Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
> ---
>  pyanaconda/constants.py    |  3 ++
>  pyanaconda/ui/gui/utils.py | 82 +++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 84 insertions(+), 1 deletion(-)
> 
> diff --git a/pyanaconda/constants.py b/pyanaconda/constants.py
> index 115ef28..48bc142 100644
> --- a/pyanaconda/constants.py
> +++ b/pyanaconda/constants.py
> @@ -143,3 +143,6 @@ PASSWORD_WEAK_CONFIRM = N_("You have provided a weak password. Press Done again
>  PASSWORD_WEAK_CONFIRM_WITH_ERROR = N_("You have provided a weak password: %s. Press Done again to use anyway.")
>  
>  PASSWORD_STRENGTH_DESC = [N_("Empty"), N_("Weak"), N_("Fair"), N_("Good"), N_("Strong")]
> +
> +# the number of seconds we consider a noticeable freeze of the UI
> +NOTICEABLE_FREEZE = 0.25

I think this should be 0.1 at the most. 250mS is a very noticeable
delay.

> +    def process_one_batch((queue, action, done_queue)):
> +        tstamp_start = time.time()
> +        tstamp = time.time()
> +
> +        # process as many batches as user cannot notice
> +        while tstamp - tstamp_start < NOTICEABLE_FREEZE:
> +            for i in xrange(batch_size):

I think you can drop the batch size. Just run them until the queue is
empty or you run out of time. By batching them up you make the delay
more granular, especially if the items being processed have different
runtimes.

> +                try:
> +                    action_item = queue.get_nowait()
> +                    if action_item is TERMINATOR:
> +                        # all items processed, tell we are finished and return
> +                        done_queue.put(None)
> +                        return False
> +                    else:
> +                        # run action on the item
> +                        action(action_item, *args)
> +                except Queue.Empty:
> +                    # empty queue, reschedule to run later
> +                    return True
> +
> +            tstamp = time.time()
> +
> +        # time out but something left, reschedule to run again later
> +        return True
> +
> +    item_queue = Queue.Queue()
> +    done_queue = Queue.Queue()

An Event object may be better for this, it probably amounts to the same
thing, but you're just using the queue to block until the processing is
done.

It would also be a good idea to add some logging, at least telling when
it started, maybe the size of the queue, and when it finished.

-- 
Brian C. Lane | Anaconda Team | IRC: bcl #anaconda | Port Orchard, WA (PST8PDT)


More information about the anaconda-patches mailing list