diff --git a/src/async_utils/_qs.py b/src/async_utils/_qs.py index 0704bac..51e4af1 100644 --- a/src/async_utils/_qs.py +++ b/src/async_utils/_qs.py @@ -192,156 +192,6 @@ def set(self, /) -> bool: return success -class Semaphore: - __slots__ = ( - "__weakref__", - "_unlocked", - "_value", - "_waiters", - ) - - def __init__(self, value: int = 1, /) -> None: - self._value: int = value - self._waiters: deque[AsyncEvent | ThreadingEvent] = deque() - self._unlocked: list[None] = [None] * self._value - - async def __aenter__(self, /) -> t.Self: - await self.async_acquire() - return self - - async def __aexit__(self, *dont_care: object) -> None: - self.release() - - def __enter__(self, /) -> t.Self: - self.sync_acquire() - - return self - - def __exit__(self, *dont_care: object) -> None: - self.release() - - def _acquire_nowait(self, /) -> bool: - if unlocked := self._unlocked: - try: - unlocked.pop() - except IndexError: - success = False - else: - success = True - else: - success = False - - return success - - async def async_acquire(self) -> bool: - waiters = self._waiters - success = self._acquire_nowait() - rescheduled = False - - if not success: - waiters.append(event := AsyncEvent()) - - try: - success = self._acquire_nowait() - - if not success: - success = await event - rescheduled = True - finally: - if success or event.cancel(): - try: - waiters.remove(event) - except ValueError: - pass - else: - self.release() - - if not rescheduled: - await asyncio.sleep(0) - - return success - - def sync_acquire( - self, /, *, blocking: bool = True, timeout: float | None = None - ) -> bool: - waiters = self._waiters - success = self._acquire_nowait() - - if success := self._acquire_nowait(): - return True - - if not blocking: - return False - - waiters.append(event := ThreadingEvent()) - - try: - success = self._acquire_nowait() - - if not success: - success = event.wait(timeout) - finally: - if success or event.cancel(): - try: - waiters.remove(event) - except ValueError: - pass - else: - self.release() - - return success - - def release(self) -> None: - waiters = self._waiters - unlocked = self._unlocked - count = 1 - - while True: - if waiters: - if not count: - if self._acquire_nowait(): - count = 1 - else: - break - - try: - event = waiters[0] - except IndexError: - pass - else: - if event.is_set(): - count -= 1 - - try: - waiters.remove(event) - except ValueError: - pass - - if count or unlocked: - continue - break - - if count == 1: - unlocked.append(None) - elif count > 1: - unlocked.extend([None] * count) - else: - break - - if waiters: - count = 0 - else: - break - - @property - def waiting(self, /) -> int: - return len(self._waiters) - - @property - def value(self, /) -> int: - return len(self._unlocked) - - class _BaseQueue[T]: __slots__ = ( "__get_waiters", diff --git a/src/async_utils/dual_color.py b/src/async_utils/dual_color.py index 7327ec3..340579f 100644 --- a/src/async_utils/dual_color.py +++ b/src/async_utils/dual_color.py @@ -14,6 +14,6 @@ from __future__ import annotations -from ._qs import LIFOQueue, PriorityQueue, Queue, QueueEmpty, QueueFull, Semaphore +from ._qs import LIFOQueue, PriorityQueue, Queue, QueueEmpty, QueueFull -__all__ = ("LIFOQueue", "PriorityQueue", "Queue", "QueueEmpty", "QueueFull", "Semaphore") +__all__ = ("LIFOQueue", "PriorityQueue", "Queue", "QueueEmpty", "QueueFull")