[ui] thumbnail cache: use thread pool to manage thread lifetime automatically

This commit is contained in:
mugulmd 2023-02-09 01:50:38 -08:00
parent db8d00e901
commit c758bf043b

View file

@ -10,6 +10,7 @@ import hashlib
import time import time
import logging import logging
from threading import Thread from threading import Thread
from multiprocessing.pool import ThreadPool
class ThumbnailCache(QObject): class ThumbnailCache(QObject):
@ -57,10 +58,9 @@ class ThumbnailCache(QObject):
thumbnailCreated = Signal(QUrl, int) thumbnailCreated = Signal(QUrl, int)
# Threads info and LIFO structure for running clean and createThumbnail asynchronously # Threads info and LIFO structure for running clean and createThumbnail asynchronously
maxWorkerThreads = 3
activeWorkerThreads = 0
requests = [] requests = []
cleaningThread = None cleaningThread = None
workerThreads = ThreadPool(processes=3)
@staticmethod @staticmethod
def initialize(): def initialize():
@ -211,11 +211,9 @@ class ThumbnailCache(QObject):
return source return source
# Thumbnail does not exist # Thumbnail does not exist
# Create request and start a thread if needed # Create request and submit to worker threads
ThumbnailCache.requests.append((imgSource, callerID)) ThumbnailCache.requests.append((imgSource, callerID))
if ThumbnailCache.activeWorkerThreads < ThumbnailCache.maxWorkerThreads: ThumbnailCache.workerThreads.apply_async(func=self.handleRequestsAsync)
thread = Thread(target=self.handleRequestsAsync)
thread.start()
return None return None
@ -264,15 +262,9 @@ class ThumbnailCache(QObject):
def handleRequestsAsync(self): def handleRequestsAsync(self):
"""Process thumbnail creation requests in LIFO order. """Process thumbnail creation requests in LIFO order.
This method is only meant to be called by worker threads,
hence it also takes care of registering/unregistering the calling thread.
Note: this operation waits for the cleaning process to finish before starting, Note: this operation waits for the cleaning process to finish before starting,
in order to avoid synchronization issues. in order to avoid synchronization issues.
""" """
# Register worker thread
ThumbnailCache.activeWorkerThreads += 1
# Wait for cleaning thread to finish # Wait for cleaning thread to finish
if ThumbnailCache.cleaningThread is not None and ThumbnailCache.cleaningThread.is_alive(): if ThumbnailCache.cleaningThread is not None and ThumbnailCache.cleaningThread.is_alive():
ThumbnailCache.cleaningThread.join() ThumbnailCache.cleaningThread.join()
@ -284,8 +276,7 @@ class ThumbnailCache(QObject):
self.createThumbnail(req[0], req[1]) self.createThumbnail(req[0], req[1])
except IndexError: except IndexError:
# No more request to process # No more request to process
# Unregister worker thread return
ThumbnailCache.activeWorkerThreads -= 1
@Slot() @Slot()
def clearRequests(self): def clearRequests(self):