- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等) - java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等) - javax/ 4个模块 (net/crypto/security/sql) - org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http) - dalvik/ 1个模块 (system) - ~3053个类/接口,方法签名完全对齐Android SDK - 桌面跨平台运行 (Windows/macOS/Linux) - 修复所有导入错误和Python关键字冲突
681 lines
19 KiB
Python
681 lines
19 KiB
Python
"""
|
|
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 |