""" Java java.util.concurrent.locks standard library APIs implemented in Python. java.util.concurrent.locks package - Lock, ReadWriteLock, ReentrantLock, etc. """ from __future__ import annotations from .._core import Stub from ..java.lang import RuntimeException # InterruptedException (桌面模拟) class InterruptedException(RuntimeException): def __init__(self, message=""): super().__init__(message) import threading as _threading import time as _time import collections as _collections __all__ = [ "Lock", "ReadWriteLock", "ReentrantLock", "ReentrantReadWriteLock", "ReentrantReadWriteLock_ReadLock", "ReentrantReadWriteLock_WriteLock", "Condition", "LockSupport", "AbstractQueuedSynchronizer", "AbstractQueuedLongSynchronizer", "AbstractOwnableSynchronizer", ] # ============================================================ # Lock interface # ============================================================ class Lock(Stub): """java.util.concurrent.locks.Lock""" def lock(self): raise NotImplementedError def lockInterruptibly(self): raise NotImplementedError def tryLock(self, time_val=None, unit=None): raise NotImplementedError def unlock(self): raise NotImplementedError def newCondition(self): raise NotImplementedError class ReadWriteLock(Stub): """java.util.concurrent.locks.ReadWriteLock""" def readLock(self): raise NotImplementedError def writeLock(self): raise NotImplementedError # ============================================================ # ReentrantLock # ============================================================ class ReentrantLock(Lock): """java.util.concurrent.locks.ReentrantLock""" def __init__(self, fair=False): super().__init__() self._lock = _threading.RLock() self._fair = fair self._owner = None self._hold_count = 0 def lock(self): self._lock.acquire() self._owner = _threading.current_thread() self._hold_count += 1 def lockInterruptibly(self): self.lock() def tryLock(self, timeout=None, unit=None): if timeout is None: acquired = self._lock.acquire(blocking=False) else: if unit is not None: timeout = timeout acquired = self._lock.acquire(blocking=True, timeout=timeout) if acquired: self._owner = _threading.current_thread() self._hold_count += 1 return True return False def unlock(self): self._hold_count -= 1 if self._hold_count == 0: self._owner = None self._lock.release() def newCondition(self): return Condition(self) def getHoldCount(self): return self._hold_count def isHeldByCurrentThread(self): return self._owner is _threading.current_thread() def isLocked(self): return self._owner is not None def isFair(self): return self._fair def getOwner(self): return self._owner def getQueuedThreads(self): return [] def getQueueLength(self): return 0 def hasQueuedThreads(self): return False def hasQueuedThread(self, thread): return False def toString(self): status = "Locked" if self.isLocked() else "Unlocked" return f"ReentrantLock[{status}, hold={self._hold_count}]" # ============================================================ # ReentrantReadWriteLock # ============================================================ class ReentrantReadWriteLock(ReadWriteLock): """java.util.concurrent.locks.ReentrantReadWriteLock""" def __init__(self, fair=False): super().__init__() self._fair = fair self._read_lock = ReentrantReadWriteLock_ReadLock(self) self._write_lock = ReentrantReadWriteLock_WriteLock(self) self._read_hold_count = 0 self._write_hold_count = 0 self._write_owner = None self._lock = _threading.RLock() self._read_lock_obj = _threading.Lock() self._read_cond = _threading.Condition(self._read_lock_obj) self._readers = 0 self._writers_waiting = 0 def readLock(self): return self._read_lock def writeLock(self): return self._write_lock def isFair(self): return self._fair def getReadLockCount(self): return self._readers def isWriteLocked(self): return self._write_owner is not None def isWriteLockedByCurrentThread(self): return self._write_owner is _threading.current_thread() def getWriteHoldCount(self): return self._write_hold_count def getReadHoldCount(self): return self._read_hold_count def getOwner(self): return self._write_owner def getQueuedWriterThreads(self): return [] def getQueuedReaderThreads(self): return [] def getQueueLength(self): return 0 def hasQueuedThreads(self): return False def hasQueuedThread(self, thread): return False def toString(self): w = self._write_hold_count r = self._readers return f"ReentrantReadWriteLock[read_locks={r}, write_locks={w}]" def _acquire_read(self): with self._lock: while self._write_owner is not None and self._write_owner != _threading.current_thread(): self._read_cond.wait() self._readers += 1 self._read_hold_count += 1 def _release_read(self): with self._lock: self._readers -= 1 self._read_hold_count -= 1 if self._readers == 0: self._read_cond.notify_all() def _acquire_write(self): self._lock.acquire() self._write_owner = _threading.current_thread() self._write_hold_count += 1 def _release_write(self): self._write_hold_count -= 1 if self._write_hold_count == 0: self._write_owner = None self._read_cond.notify_all() self._lock.release() class ReentrantReadWriteLock_ReadLock(Lock): """java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock""" def __init__(self, rw_lock): super().__init__() self._rw_lock = rw_lock def lock(self): self._rw_lock._acquire_read() def lockInterruptibly(self): self.lock() def tryLock(self, timeout=None, unit=None): self.lock() return True def unlock(self): self._rw_lock._release_read() def newCondition(self): raise UnsupportedOperationException("Read locks do not support Condition") class ReentrantReadWriteLock_WriteLock(Lock): """java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock""" def __init__(self, rw_lock): super().__init__() self._rw_lock = rw_lock def lock(self): self._rw_lock._acquire_write() def lockInterruptibly(self): self.lock() def tryLock(self, timeout=None, unit=None): if timeout is None: acquired = self._rw_lock._lock.acquire(blocking=False) else: acquired = self._rw_lock._lock.acquire(blocking=True, timeout=timeout) if acquired: self._rw_lock._write_owner = _threading.current_thread() self._rw_lock._write_hold_count += 1 return True return False def unlock(self): self._rw_lock._release_write() def newCondition(self): return Condition(self) def isHeldByCurrentThread(self): return self._rw_lock._write_owner is _threading.current_thread() # ============================================================ # Condition # ============================================================ class Condition(Stub): """java.util.concurrent.locks.Condition""" def __init__(self, lock=None): super().__init__() self._lock = lock self._cond = _threading.Condition(_threading.RLock()) if lock is None else _threading.Condition() def await_signal(self, time_val=None, unit=None): self._cond.acquire() try: if time_val is None: self._cond.wait() return True else: if unit is not None: secs = time_val / 1000.0 # milliseconds else: secs = float(time_val) self._cond.wait(timeout=secs) return True finally: self._cond.release() def awaitUninterruptibly(self): self.await_signal() def awaitNanos(self, nanos_timeout): self.await_signal(nanos_timeout / 1000000.0) return 0 def awaitUntil(self, deadline): now = _time.time() diff = deadline - now if diff > 0: self.await_signal(diff) return True def signal(self): self._cond.acquire() try: self._cond.notify() finally: self._cond.release() def signalAll(self): self._cond.acquire() try: self._cond.notify_all() finally: self._cond.release() # ============================================================ # LockSupport # ============================================================ class LockSupport(Stub): """java.util.concurrent.locks.LockSupport""" _blocked = {} @staticmethod def park(blocker=None): if blocker is not None: LockSupport._blocked[_threading.current_thread().ident] = blocker _time.sleep(0.01) if blocker is not None: del LockSupport._blocked[_threading.current_thread().ident] @staticmethod def parkNanos(nanos, blocker=None): if blocker is not None: LockSupport._blocked[_threading.current_thread().ident] = blocker _time.sleep(nanos / 1000000000.0) if blocker is not None: del LockSupport._blocked[_threading.current_thread().ident] @staticmethod def parkUntil(deadline, blocker=None): now = _time.time() diff = deadline - now if diff > 0: if blocker is not None: LockSupport._blocked[_threading.current_thread().ident] = blocker _time.sleep(diff) if blocker is not None: del LockSupport._blocked[_threading.current_thread().ident] @staticmethod def unpark(thread): pass @staticmethod def getBlocker(thread): return LockSupport._blocked.get(thread.ident) # ============================================================ # AbstractOwnableSynchronizer # ============================================================ class AbstractOwnableSynchronizer(Stub): """java.util.concurrent.locks.AbstractOwnableSynchronizer""" def __init__(self): super().__init__() self._exclusive_owner_thread = None def setExclusiveOwnerThread(self, thread): self._exclusive_owner_thread = thread def getExclusiveOwnerThread(self): return self._exclusive_owner_thread # ============================================================ # AbstractQueuedSynchronizer # ============================================================ class AbstractQueuedSynchronizer(AbstractOwnableSynchronizer): """java.util.concurrent.locks.AbstractQueuedSynchronizer""" class ConditionObject(Condition): def __init__(self, sync): super().__init__() self._sync = sync def __init__(self): super().__init__() self._state = 0 self._lock = _threading.Lock() self._cond = _threading.Condition(self._lock) self._head = None self._tail = None self._wait_queue = _collections.deque() def getState(self): with self._lock: return self._state def setState(self, new_state): with self._lock: self._state = new_state def compareAndSetState(self, expect, update): with self._lock: if self._state == expect: self._state = int(update) return True return False def acquire(self, arg): if not self.tryAcquire(arg): self._acquire_queued(self._add_waiter(), arg) def acquireInterruptibly(self, arg): self.acquire(arg) def tryAcquireNanos(self, arg, nanos_timeout): return self.tryAcquire(arg) def release(self, arg): if self.tryRelease(arg): self._signal_next() return True return False def acquireShared(self, arg): if self.tryAcquireShared(arg) < 0: self._acquire_shared_queued(self._add_waiter(), arg) def acquireSharedInterruptibly(self, arg): self.acquireShared(arg) def tryAcquireSharedNanos(self, arg, nanos_timeout): return self.tryAcquireShared(arg) >= 0 def releaseShared(self, arg): if self.tryReleaseShared(arg): self._signal_next() return True return False def tryAcquire(self, arg): raise NotImplementedError def tryRelease(self, arg): raise NotImplementedError def tryAcquireShared(self, arg): return 1 def tryReleaseShared(self, arg): return True def isHeldExclusively(self): return self.getExclusiveOwnerThread() is _threading.current_thread() def getQueuedThreads(self): return list(self._wait_queue) def getQueueLength(self): return len(self._wait_queue) def hasQueuedThreads(self): return len(self._wait_queue) > 0 def hasContended(self): return len(self._wait_queue) > 0 def getFirstQueuedThread(self): if self._wait_queue: return self._wait_queue[0] return None def owns(self, condition): return isinstance(condition, AbstractQueuedSynchronizer.ConditionObject) def hasWaiters(self, condition): return False def getWaitQueueLength(self, condition): return 0 def getWaitingThreads(self, condition): return [] def toString(self): return f"AbstractQueuedSynchronizer[state={self._state}]" def _add_waiter(self): thread = _threading.current_thread() with self._lock: self._wait_queue.append(thread) return thread def _acquire_queued(self, node, arg): while True: if self.tryAcquire(arg): with self._lock: if node in self._wait_queue: self._wait_queue.remove(node) return _time.sleep(0.001) def _acquire_shared_queued(self, node, arg): while True: if self.tryAcquireShared(arg) >= 0: with self._lock: if node in self._wait_queue: self._wait_queue.remove(node) return _time.sleep(0.001) def _signal_next(self): with self._lock: if self._wait_queue: self._cond.notify() # ============================================================ # AbstractQueuedLongSynchronizer # ============================================================ class AbstractQueuedLongSynchronizer(AbstractOwnableSynchronizer): """java.util.concurrent.locks.AbstractQueuedLongSynchronizer""" class ConditionObject(Condition): def __init__(self, sync): super().__init__() self._sync = sync def __init__(self): super().__init__() self._state = 0 self._lock = _threading.Lock() self._cond = _threading.Condition(self._lock) self._wait_queue = _collections.deque() def getState(self): with self._lock: return self._state def setState(self, new_state): with self._lock: self._state = int(new_state) def compareAndSetState(self, expect, update): with self._lock: if self._state == expect: self._state = int(update) return True return False def acquire(self, arg): if not self.tryAcquire(arg): self._acquire_queued(self._add_waiter(), arg) def acquireInterruptibly(self, arg): self.acquire(arg) def tryAcquireNanos(self, arg, nanos_timeout): return self.tryAcquire(arg) def release(self, arg): if self.tryRelease(arg): self._signal_next() return True return False def acquireShared(self, arg): if self.tryAcquireShared(arg) < 0: self._acquire_shared_queued(self._add_waiter(), arg) def acquireSharedInterruptibly(self, arg): self.acquireShared(arg) def tryAcquireSharedNanos(self, arg, nanos_timeout): return self.tryAcquireShared(arg) >= 0 def releaseShared(self, arg): if self.tryReleaseShared(arg): self._signal_next() return True return False def tryAcquire(self, arg): raise NotImplementedError def tryRelease(self, arg): raise NotImplementedError def tryAcquireShared(self, arg): return 1 def tryReleaseShared(self, arg): return True def isHeldExclusively(self): return self.getExclusiveOwnerThread() is _threading.current_thread() def getQueuedThreads(self): return list(self._wait_queue) def getQueueLength(self): return len(self._wait_queue) def hasQueuedThreads(self): return len(self._wait_queue) > 0 def getFirstQueuedThread(self): if self._wait_queue: return self._wait_queue[0] return None def toString(self): return f"AbstractQueuedLongSynchronizer[state={self._state}]" def _add_waiter(self): thread = _threading.current_thread() with self._lock: self._wait_queue.append(thread) return thread def _acquire_queued(self, node, arg): while True: if self.tryAcquire(arg): with self._lock: if node in self._wait_queue: self._wait_queue.remove(node) return _time.sleep(0.001) def _acquire_shared_queued(self, node, arg): while True: if self.tryAcquireShared(arg) >= 0: with self._lock: if node in self._wait_queue: self._wait_queue.remove(node) return _time.sleep(0.001) def _signal_next(self): with self._lock: if self._wait_queue: self._cond.notify() # ============================================================ # UnsupportedOperationException # ============================================================ class UnsupportedOperationException(RuntimeException): """java.lang.UnsupportedOperationException""" pass