From a62ad5f70cbae026d64d183117a3ec02de59444c Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 21 Sep 2010 20:20:34 +0100 Subject: [PATCH] Use one queue object in FunctionDispatch. Theory: the producer (Qt GUI cover function) exists only once per instance of FunctionDispatcher. This follows from the fact that the dispatcher instance is created on the recipient thread. The consumer (the cover cache) could in theory be multiple threads (but it isn't). Because the items produced by the producer are not equivalent, we need to ensure that the order of items put in the queue by the producer is equal to the order of the requests. To guarantee this order, regardless of the number of consumer threads, we ensure that only one request to the producer can be outstanding. --- src/calibre/gui2/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 66e199b8a0..8cfcc17eba 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -1,7 +1,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' """ The GUI """ -import os, sys, Queue +import os, sys, Queue, threading from threading import RLock from PyQt4.Qt import QVariant, QFileInfo, QObject, SIGNAL, QBuffer, Qt, \ @@ -311,11 +311,14 @@ class FunctionDispatcher(QObject): if not queued: typ = Qt.AutoConnection if queued is None else Qt.DirectConnection self.dispatch_signal.connect(self.dispatch, type=typ) + self.q = Queue.Queue() + self.lock = threading.Lock() def __call__(self, *args, **kwargs): - q = Queue.Queue() - self.dispatch_signal.emit(q, args, kwargs) - return q.get() + with self.lock: + self.dispatch_signal.emit(self.q, args, kwargs) + res = self.q.get() + return res def dispatch(self, q, args, kwargs): try: