From 1f7a3e3d36f8ea600dc060b44668629cea8ef0db Mon Sep 17 00:00:00 2001 From: Markil 3 Date: Sat, 2 Aug 2025 14:01:00 -0600 Subject: [PATCH] Fixes the way threading works --- __main__.py | 2 +- comic_download/comic_strip.py | 59 +++++++++++++++-------------------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/__main__.py b/__main__.py index a02571d..68d18c7 100644 --- a/__main__.py +++ b/__main__.py @@ -87,7 +87,7 @@ if __name__ == "__main__": r = r[start - 1:end] for index in reversed(r): - t = threading.Thread(name=str(comic) + str(index), target=load_strip, args=(base_path, comic, index, args.plain, thread_limit)) + t = threading.Thread(name=str(comic.get_identifier_string()) + "-" + str(index), target=load_strip, args=(base_path, comic, index, args.plain, thread_limit)) threads.append(t) t.start() diff --git a/comic_download/comic_strip.py b/comic_download/comic_strip.py index 6f862d5..a79c8e6 100644 --- a/comic_download/comic_strip.py +++ b/comic_download/comic_strip.py @@ -5,7 +5,7 @@ import logging.handlers import argparse from abc import ABC, abstractmethod from datetime import datetime -from threading import Lock +from threading import Lock, Condition import bisect import time import re @@ -102,9 +102,9 @@ class ImageRepo(ABC): self._data_loaded = False """A flag for when the data has been successfully loaded.""" - self._load_lock = Lock() + self._load_lock = Condition(Lock()) """A lock for enforcing thread safety when loading this repository.""" - self._download_lock = Lock() + self._download_lock = Condition(Lock()) """A lock for enforcing thread safety when downloading secondary resources.""" def get_identifier_string(self): @@ -122,7 +122,7 @@ class ImageRepo(ABC): :returns: True if the data has been fully loaded, false otherwise. """ - return not self._load_lock.locked() and self._data_loaded + return not self._load_lock._lock.locked() and self._data_loaded def is_downloaded(self): """ @@ -130,7 +130,7 @@ class ImageRepo(ABC): :returns: True if the images have been fully downloaded, false otherwise. """ - return not self.image_urls or (not self._download_lock.locked() and self.images) + return not self.image_urls or (not self._download_lock._lock.locked() and self.images) def load_data(self): """ @@ -147,12 +147,12 @@ class ImageRepo(ABC): :see: #await_load :see: #_load_data """ - if not self._load_lock.locked() and not self._data_loaded: - if self._load_lock.acquire(): + with self._load_lock: + if not self._data_loaded: self._load_data() logging.info("Completed loading of %s", self.get_identifier_string()) self._data_loaded = True - self._load_lock.release() + self._load_lock.notify_all() def await_load(self): """ @@ -162,12 +162,8 @@ class ImageRepo(ABC): :see: #load_data """ - if self._load_lock.locked(): - self._load_lock.acquire() - self._load_lock.release() - else: - # Loads this ourselves - self.load_data() + # Loads this ourselves + self.load_data() @abstractmethod @@ -200,12 +196,13 @@ class ImageRepo(ABC): if not self.is_loaded(): raise SequenceException("Cannot download images before first loading performed.") - # Checks to see if we need to download and that one is not already in progress - if not self._download_lock.locked() and self.image_urls and not self.images: - if self._download_lock.acquire(): + with self._download_lock: + # Checks to see if we need to download and that one is not already in progress + if self.image_urls and not self.images: + logging.info("Downloading %s", self.get_identifier_string()) self._download_data() logging.info("Completed downloading of %s", self.get_identifier_string()) - self._download_lock.release() + self._download_lock.notify_all() def await_download(self): """ @@ -215,12 +212,7 @@ class ImageRepo(ABC): :see: #download_data """ - if self._download_lock.locked(): - self._download_lock.acquire() - self._download_lock.release() - else: - # Downloads this ourselves - self.download_data() + self.download_data() def _download_data(self): """ @@ -346,7 +338,7 @@ class ComicStrip(ImageRepo, ABC): """A list of captions for each panel.""" self.date = None """The date that the comic was published.""" - self._transform_lock = Lock() + self._transform_lock = Condition(Lock()) """A lock for enforcing thread safety when transforming resources.""" self.transformed_images = [] """A list of NamedTemporaryFiles linking to the transformed versions of the image downloads.""" @@ -438,21 +430,20 @@ class ComicStrip(ImageRepo, ABC): if not self.is_downloaded(): raise SequenceException("Cannot package comic strip before strip data has been fully downloaded.") if not self.comic.is_loaded(): - raise SequenceException("Cannot package comic before data has been fully loaded.") + raise SequenceException("Cannot package comic strip before comic data has been fully loaded.") if not self.comic.is_downloaded(): - raise SequenceException("Cannot package comic before data has been fully downloaded.") + raise SequenceException("Cannot package comic strip before comic data has been fully downloaded.") if not self.transformed_images: if not self._transformed: - if self._transform_lock.locked(): + if self._transform_lock._lock.locked(): # Await for the existing transform to complete - self._transform_lock.acquire() - self._transform_lock.release() + self._transform_lock.wait() else: # Run the transformation outselves - self._transform_lock.acquire() - self._transform_images() - self._transformed = True - self._transform_lock.release() + with self._transform_lock: + self._transform_images() + self._transformed = True + self._transform_lock.notify_all() with ZipFile(self.get_package_path(base_path), 'w') as comic_zip: for i in range(len(self.transformed_images)): image = self.transformed_images[i]