genshin-wiki/utils/single.py

56 lines
1.2 KiB
Python
Raw Normal View History

2023-04-15 05:09:56 +00:00
from multiprocessing import RLock as Lock
from typing import (
ClassVar,
Generic,
Optional,
TYPE_CHECKING,
Type,
TypeVar,
)
from typing_extensions import Self
if TYPE_CHECKING:
from multiprocessing.synchronize import RLock as LockType
__all__ = ["singleton", "Singleton"]
T = TypeVar("T")
class _Singleton(Generic[T]):
lock: ClassVar["LockType"] = Lock()
__slots__ = "cls", "instance"
cls: Type[T]
instance: Optional[T]
def __init__(self, cls: Type[T]):
self.cls = cls
self.instance = None
def __call__(self, *args, **kwargs) -> T:
with self.lock:
if self.instance is None or args or kwargs:
self.instance = self.cls(*args, **kwargs)
return self.instance
def singleton(cls: Optional[Type[T]] = None) -> Type[T]:
def wrap(_cls: Type[T]) -> _Singleton[T]:
return _Singleton(_cls)
return wrap if cls is None else wrap(cls)
class Singleton(object):
_lock: ClassVar["LockType"] = Lock()
_instance: ClassVar[Optional[Self]] = None
def __new__(cls: Type[T], *args, **kwargs) -> T:
with cls._lock:
if cls._instance is None:
cls._instance = object.__new__(cls)
return cls._instance