From fadbef84e160c3c98f0a791d7b45850f1449cb75 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Thu, 13 Jul 2023 18:56:10 +0200 Subject: [PATCH] Fix `Arial.ttf` threaded multi-download bug (#3725) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- ultralytics/yolo/utils/__init__.py | 30 ++++++++++++++++++++++++++++++ ultralytics/yolo/utils/checks.py | 7 ++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ultralytics/yolo/utils/__init__.py b/ultralytics/yolo/utils/__init__.py index bcfce51..5160322 100644 --- a/ultralytics/yolo/utils/__init__.py +++ b/ultralytics/yolo/utils/__init__.py @@ -252,6 +252,36 @@ if WINDOWS: # emoji-safe logging LOGGER.addFilter(EmojiFilter()) +class ThreadingLocked: + """ + A decorator class for ensuring thread-safe execution of a function or method. + This class can be used as a decorator to make sure that if the decorated function + is called from multiple threads, only one thread at a time will be able to execute the function. + + Attributes: + lock (threading.Lock): A lock object used to manage access to the decorated function. + + Usage: + @ThreadingLocked() + def my_function(): + # Your code here + pass + """ + + def __init__(self): + self.lock = threading.Lock() + + def __call__(self, f): + from functools import wraps + + @wraps(f) + def decorated(*args, **kwargs): + with self.lock: + return f(*args, **kwargs) + + return decorated + + def yaml_save(file='data.yaml', data=None): """ Save YAML data to a file. diff --git a/ultralytics/yolo/utils/checks.py b/ultralytics/yolo/utils/checks.py index 5724b60..5908d3b 100644 --- a/ultralytics/yolo/utils/checks.py +++ b/ultralytics/yolo/utils/checks.py @@ -20,9 +20,9 @@ import requests import torch from matplotlib import font_manager -from ultralytics.yolo.utils import (AUTOINSTALL, LOGGER, ONLINE, ROOT, USER_CONFIG_DIR, TryExcept, clean_url, colorstr, - downloads, emojis, is_colab, is_docker, is_jupyter, is_kaggle, is_online, - is_pip_package, url2file) +from ultralytics.yolo.utils import (AUTOINSTALL, LOGGER, ONLINE, ROOT, USER_CONFIG_DIR, ThreadingLocked, TryExcept, + clean_url, colorstr, downloads, emojis, is_colab, is_docker, is_jupyter, is_kaggle, + is_online, is_pip_package, url2file) def is_ascii(s) -> bool: @@ -155,6 +155,7 @@ def check_pip_update_available(): return False +@ThreadingLocked() def check_font(font='Arial.ttf'): """ Find font locally or download to user's configuration directory if it does not already exist.