2037 lines
52 KiB
Python
2037 lines
52 KiB
Python
"""
|
|
Java util.concurrent standard library APIs implemented in Python.
|
|
java.util.concurrent package - Executors, ThreadPoolExecutor, CountDownLatch, etc.
|
|
"""
|
|
|
|
from .._core import Stub
|
|
from .lang import RuntimeException
|
|
import threading as _threading
|
|
import concurrent.futures as _futures
|
|
import time as _time
|
|
import queue as _queue
|
|
import math as _py_math
|
|
|
|
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
|
CancellationException = type("CancellationException", (RuntimeException,), {})
|
|
ExecutionException = type("ExecutionException", (RuntimeException,), {})
|
|
RejectedExecutionException = type("RejectedExecutionException", (RuntimeException,), {})
|
|
TimeoutException = type("TimeoutException", (RuntimeException,), {})
|
|
BrokenBarrierException = type("BrokenBarrierException", (RuntimeException,), {})
|
|
CompletionException = type("CompletionException", (RuntimeException,), {})
|
|
|
|
__all__ = [
|
|
"Executors", "ExecutorService", "Executor", "ExecutorCompletionService",
|
|
"ThreadPoolExecutor", "AbstractExecutorService",
|
|
"ScheduledExecutorService", "ScheduledThreadPoolExecutor",
|
|
"FutureTask", "Future", "RunnableFuture", "RunnableScheduledFuture",
|
|
"Callable", "CompletionService", "CompletionStage",
|
|
"CountDownLatch", "CyclicBarrier", "Semaphore", "Phaser", "Exchanger",
|
|
"TimeUnit",
|
|
"TimeoutException", "CancellationException", "ExecutionException",
|
|
"RejectedExecutionException", "BrokenBarrierException",
|
|
"CompletionException",
|
|
"ConcurrentHashMap", "CopyOnWriteArrayList", "CopyOnWriteArraySet",
|
|
"ConcurrentLinkedQueue", "ConcurrentLinkedDeque",
|
|
"DelayQueue", "SynchronousQueue", "LinkedBlockingQueue",
|
|
"ArrayBlockingQueue", "PriorityBlockingQueue",
|
|
"BlockingQueue", "BlockingDeque",
|
|
"AtomicBoolean", "AtomicInteger", "AtomicLong", "AtomicReference",
|
|
"AtomicIntegerArray", "AtomicLongArray", "AtomicReferenceArray",
|
|
"AtomicIntegerFieldUpdater", "AtomicLongFieldUpdater",
|
|
"AtomicReferenceFieldUpdater",
|
|
"AtomicMarkableReference", "AtomicStampedReference",
|
|
"DoubleAccumulator", "DoubleAdder",
|
|
"LongAccumulator", "LongAdder",
|
|
"Lock", "ReentrantLock", "ReentrantReadWriteLock",
|
|
"ReadWriteLock", "Condition", "LockSupport",
|
|
"AbstractQueuedSynchronizer", "AbstractQueuedLongSynchronizer",
|
|
"Flow", "SubmissionPublisher",
|
|
"RecursiveAction", "RecursiveTask", "ForkJoinPool",
|
|
"ForkJoinTask", "ForkJoinWorkerThread",
|
|
"CompletableFuture",
|
|
]
|
|
|
|
|
|
# ============================================================
|
|
# Interfaces
|
|
# ============================================================
|
|
|
|
class Callable(Stub):
|
|
def call(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class Future(Stub):
|
|
def get(self, timeout=None, unit=None):
|
|
raise NotImplementedError
|
|
|
|
def cancel(self, may_interrupt):
|
|
raise NotImplementedError
|
|
|
|
def isCancelled(self):
|
|
raise NotImplementedError
|
|
|
|
def isDone(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class RunnableFuture(Future):
|
|
def run(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class RunnableScheduledFuture(RunnableFuture):
|
|
def isPeriodic(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class CompletionService(Stub):
|
|
def submit(self, task):
|
|
raise NotImplementedError
|
|
|
|
def take(self):
|
|
raise NotImplementedError
|
|
|
|
def poll(self, timeout=0, unit=None):
|
|
raise NotImplementedError
|
|
|
|
|
|
class CompletionStage(Stub):
|
|
pass
|
|
|
|
|
|
class Executor(Stub):
|
|
def execute(self, command):
|
|
raise NotImplementedError
|
|
|
|
|
|
class ExecutorService(Executor):
|
|
def submit(self, task, *args):
|
|
raise NotImplementedError
|
|
|
|
def shutdown(self):
|
|
raise NotImplementedError
|
|
|
|
def shutdownNow(self):
|
|
raise NotImplementedError
|
|
|
|
def isShutdown(self):
|
|
raise NotImplementedError
|
|
|
|
def isTerminated(self):
|
|
raise NotImplementedError
|
|
|
|
def awaitTermination(self, timeout, unit):
|
|
raise NotImplementedError
|
|
|
|
def invokeAll(self, tasks):
|
|
raise NotImplementedError
|
|
|
|
def invokeAny(self, tasks):
|
|
raise NotImplementedError
|
|
|
|
|
|
class ScheduledExecutorService(ExecutorService):
|
|
def schedule(self, command, delay, unit):
|
|
raise NotImplementedError
|
|
|
|
def scheduleAtFixedRate(self, command, initial_delay, period, unit):
|
|
raise NotImplementedError
|
|
|
|
def scheduleWithFixedDelay(self, command, initial_delay, delay, unit):
|
|
raise NotImplementedError
|
|
|
|
|
|
# ============================================================
|
|
# Runnable
|
|
# ============================================================
|
|
|
|
class Runnable(Stub):
|
|
def run(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
# ============================================================
|
|
# FutureTask
|
|
# ============================================================
|
|
|
|
class FutureTask(RunnableFuture):
|
|
def __init__(self, callable_or_runnable, result=None):
|
|
super().__init__()
|
|
self._callable = callable_or_runnable if isinstance(callable_or_runnable, Callable) else None
|
|
self._runnable = callable_or_runnable if isinstance(callable_or_runnable, Runnable) else None
|
|
self._result = result
|
|
self._done = False
|
|
self._cancelled = False
|
|
self._exception = None
|
|
self._lock = _threading.RLock()
|
|
self._done_event = _threading.Event()
|
|
|
|
def run(self):
|
|
if self._cancelled:
|
|
return
|
|
try:
|
|
if self._callable:
|
|
self._result = self._callable.call()
|
|
elif self._runnable:
|
|
self._runnable.run()
|
|
with self._lock:
|
|
self._done = True
|
|
self._done_event.set()
|
|
except Exception as e:
|
|
with self._lock:
|
|
self._exception = e
|
|
self._done = True
|
|
self._done_event.set()
|
|
|
|
def get(self, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
if not self._done_event.wait(seconds):
|
|
raise TimeoutException()
|
|
else:
|
|
self._done_event.wait()
|
|
with self._lock:
|
|
if self._exception:
|
|
raise ExecutionException(str(self._exception))
|
|
return self._result
|
|
|
|
def cancel(self, may_interrupt):
|
|
with self._lock:
|
|
if self._done:
|
|
return False
|
|
self._cancelled = True
|
|
self._done = True
|
|
self._done_event.set()
|
|
return True
|
|
|
|
def isCancelled(self):
|
|
return self._cancelled
|
|
|
|
def isDone(self):
|
|
return self._done
|
|
|
|
def doneTask(self):
|
|
pass
|
|
|
|
def set(self, v):
|
|
with self._lock:
|
|
self._result = v
|
|
self._done = True
|
|
self._done_event.set()
|
|
|
|
def setException(self, ex):
|
|
with self._lock:
|
|
self._exception = ex
|
|
self._done = True
|
|
self._done_event.set()
|
|
|
|
|
|
# ============================================================
|
|
# CompletableFuture
|
|
# ============================================================
|
|
|
|
class CompletableFuture(Future):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._result = None
|
|
self._exception = None
|
|
self._done = False
|
|
self._lock = _threading.RLock()
|
|
self._done_event = _threading.Event()
|
|
self._callbacks = []
|
|
|
|
def _run_callbacks(self):
|
|
for cb in self._callbacks:
|
|
try:
|
|
cb(self)
|
|
except Exception:
|
|
pass
|
|
|
|
def complete(self, result):
|
|
with self._lock:
|
|
if self._done:
|
|
return self
|
|
self._result = result
|
|
self._done = True
|
|
self._done_event.set()
|
|
self._run_callbacks()
|
|
return self
|
|
|
|
def completeExceptionally(self, ex):
|
|
with self._lock:
|
|
if self._done:
|
|
return self
|
|
self._exception = ex
|
|
self._done = True
|
|
self._done_event.set()
|
|
self._run_callbacks()
|
|
return self
|
|
|
|
def cancel(self, may_interrupt):
|
|
with self._lock:
|
|
if self._done:
|
|
return False
|
|
self._cancelled = True
|
|
self._done = True
|
|
self._done_event.set()
|
|
self._run_callbacks()
|
|
return True
|
|
|
|
def get(self, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
if not self._done_event.wait(seconds):
|
|
raise TimeoutException()
|
|
else:
|
|
self._done_event.wait()
|
|
with self._lock:
|
|
if self._exception:
|
|
raise ExecutionException(str(self._exception))
|
|
return self._result
|
|
|
|
def join(self):
|
|
return self.get()
|
|
|
|
def isDone(self):
|
|
return self._done
|
|
|
|
def isCancelled(self):
|
|
return getattr(self, "_cancelled", False)
|
|
|
|
def thenApply(self, fn):
|
|
future = CompletableFuture()
|
|
def cb(f):
|
|
try:
|
|
future.complete(fn(f.get()))
|
|
except Exception as e:
|
|
future.completeExceptionally(e)
|
|
self._callbacks.append(cb)
|
|
return future
|
|
|
|
def thenAccept(self, fn):
|
|
future = CompletableFuture()
|
|
def cb(f):
|
|
try:
|
|
fn(f.get())
|
|
future.complete(None)
|
|
except Exception as e:
|
|
future.completeExceptionally(e)
|
|
self._callbacks.append(cb)
|
|
return future
|
|
|
|
def thenRun(self, action):
|
|
future = CompletableFuture()
|
|
def cb(f):
|
|
try:
|
|
action.run()
|
|
future.complete(None)
|
|
except Exception as e:
|
|
future.completeExceptionally(e)
|
|
self._callbacks.append(cb)
|
|
return future
|
|
|
|
def thenCombine(self, other, fn):
|
|
future = CompletableFuture()
|
|
def cb(f):
|
|
try:
|
|
other_result = other.get()
|
|
future.complete(fn(f.get(), other_result))
|
|
except Exception as e:
|
|
future.completeExceptionally(e)
|
|
self._callbacks.append(cb)
|
|
return future
|
|
|
|
def thenCompose(self, fn):
|
|
future = CompletableFuture()
|
|
def cb(f):
|
|
try:
|
|
next_future = fn(f.get())
|
|
future.complete(next_future.get())
|
|
except Exception as e:
|
|
future.completeExceptionally(e)
|
|
self._callbacks.append(cb)
|
|
return future
|
|
|
|
def exceptionally(self, fn):
|
|
future = CompletableFuture()
|
|
def cb(f):
|
|
try:
|
|
f.get()
|
|
future.complete(f._result)
|
|
except Exception as e:
|
|
try:
|
|
fallback = fn(e)
|
|
future.complete(fallback)
|
|
except Exception as e2:
|
|
future.completeExceptionally(e2)
|
|
self._callbacks.append(cb)
|
|
return future
|
|
|
|
@staticmethod
|
|
def completedFuture(result):
|
|
f = CompletableFuture()
|
|
f.complete(result)
|
|
return f
|
|
|
|
@staticmethod
|
|
def failedFuture(exception):
|
|
f = CompletableFuture()
|
|
f.completeExceptionally(exception)
|
|
return f
|
|
|
|
@staticmethod
|
|
def supplyAsync(supplier, executor=None):
|
|
f = CompletableFuture()
|
|
def run():
|
|
try:
|
|
f.complete(supplier.get())
|
|
except Exception as e:
|
|
f.completeExceptionally(e)
|
|
t = _threading.Thread(target=run, daemon=True)
|
|
t.start()
|
|
return f
|
|
|
|
@staticmethod
|
|
def runAsync(runnable, executor=None):
|
|
f = CompletableFuture()
|
|
def run():
|
|
try:
|
|
runnable.run()
|
|
f.complete(None)
|
|
except Exception as e:
|
|
f.completeExceptionally(e)
|
|
t = _threading.Thread(target=run, daemon=True)
|
|
t.start()
|
|
return f
|
|
|
|
@staticmethod
|
|
def allOf(*futures):
|
|
result = CompletableFuture()
|
|
def check_all():
|
|
for f in futures:
|
|
f.get()
|
|
result.complete(None)
|
|
t = _threading.Thread(target=check_all, daemon=True)
|
|
t.start()
|
|
return result
|
|
|
|
@staticmethod
|
|
def anyOf(*futures):
|
|
result = CompletableFuture()
|
|
def check_any():
|
|
while True:
|
|
for f in futures:
|
|
if f.isDone():
|
|
result.complete(f.get())
|
|
return
|
|
_time.sleep(0.01)
|
|
t = _threading.Thread(target=check_any, daemon=True)
|
|
t.start()
|
|
return result
|
|
|
|
|
|
# ============================================================
|
|
# Executors
|
|
# ============================================================
|
|
|
|
class Executors(Stub):
|
|
@staticmethod
|
|
def newCachedThreadPool():
|
|
pool = ThreadPoolExecutor(0, _futures.ThreadPoolExecutor(max_workers=10))
|
|
pool._executor._max_workers = None
|
|
return pool
|
|
|
|
@staticmethod
|
|
def newFixedThreadPool(n_threads):
|
|
return ThreadPoolExecutor(n_threads, _futures.ThreadPoolExecutor(max_workers=n_threads))
|
|
|
|
@staticmethod
|
|
def newSingleThreadExecutor():
|
|
return ThreadPoolExecutor(1, _futures.ThreadPoolExecutor(max_workers=1))
|
|
|
|
@staticmethod
|
|
def newScheduledThreadPool(core_pool_size):
|
|
return ScheduledThreadPoolExecutor(core_pool_size)
|
|
|
|
@staticmethod
|
|
def newWorkStealingPool(parallelism=None):
|
|
return ThreadPoolExecutor(parallelism or 4, _futures.ThreadPoolExecutor(max_workers=parallelism or 4))
|
|
|
|
@staticmethod
|
|
def defaultThreadFactory():
|
|
return _threading.Thread
|
|
|
|
@staticmethod
|
|
def privilegedThreadFactory():
|
|
return _threading.Thread
|
|
|
|
@staticmethod
|
|
def callable(runnable, result=None):
|
|
class _Callable(Callable):
|
|
def call(self):
|
|
if runnable:
|
|
runnable.run()
|
|
return result
|
|
return _Callable()
|
|
|
|
|
|
# ============================================================
|
|
# ThreadPoolExecutor
|
|
# ============================================================
|
|
|
|
class ThreadPoolExecutor(ExecutorService):
|
|
def __init__(self, core_pool_size, executor=None):
|
|
super().__init__()
|
|
self._executor = executor or _futures.ThreadPoolExecutor(max_workers=core_pool_size)
|
|
self._core_pool_size = core_pool_size
|
|
self._max_pool_size = core_pool_size
|
|
self._keep_alive_time = 60
|
|
self._allow_core_thread_timeout = False
|
|
|
|
def execute(self, command):
|
|
def _run():
|
|
try:
|
|
command.run()
|
|
except Exception:
|
|
pass
|
|
self._executor.submit(_run)
|
|
|
|
def submit(self, task, *args):
|
|
if isinstance(task, Callable):
|
|
future = FutureTask(task)
|
|
self._executor.submit(future.run)
|
|
return future
|
|
elif isinstance(task, Runnable):
|
|
future = FutureTask(task)
|
|
self._executor.submit(future.run)
|
|
return future
|
|
else:
|
|
future = FutureTask(task)
|
|
self._executor.submit(future.run)
|
|
return future
|
|
|
|
def shutdown(self):
|
|
self._executor.shutdown(wait=False)
|
|
|
|
def shutdownNow(self):
|
|
self._executor.shutdown(wait=False)
|
|
|
|
def isShutdown(self):
|
|
return self._executor._shutdown
|
|
|
|
def isTerminated(self):
|
|
return self._executor._shutdown
|
|
|
|
def awaitTermination(self, timeout, unit):
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
self._executor.shutdown(wait=True)
|
|
|
|
def getPoolSize(self):
|
|
return self._core_pool_size
|
|
|
|
def getActiveCount(self):
|
|
return 0
|
|
|
|
def getTaskCount(self):
|
|
return 0
|
|
|
|
def getCompletedTaskCount(self):
|
|
return 0
|
|
|
|
def getLargestPoolSize(self):
|
|
return self._core_pool_size
|
|
|
|
def setCorePoolSize(self, size):
|
|
self._core_pool_size = size
|
|
|
|
def setMaximumPoolSize(self, size):
|
|
self._max_pool_size = size
|
|
|
|
def setKeepAliveTime(self, time, unit):
|
|
self._keep_alive_time = unit.toMillis(time) / 1000.0
|
|
|
|
def prestartAllCoreThreads(self):
|
|
pass
|
|
|
|
def prestartCoreThread(self):
|
|
pass
|
|
|
|
def allowsCoreThreadTimeOut(self):
|
|
return self._allow_core_thread_timeout
|
|
|
|
def setRejectedExecutionHandler(self, handler):
|
|
pass
|
|
|
|
def getRejectedExecutionHandler(self):
|
|
return None
|
|
|
|
|
|
class AbstractExecutorService(ExecutorService):
|
|
pass
|
|
|
|
|
|
# ============================================================
|
|
# ScheduledThreadPoolExecutor
|
|
# ============================================================
|
|
|
|
class ScheduledThreadPoolExecutor(ThreadPoolExecutor, ScheduledExecutorService):
|
|
def __init__(self, core_pool_size):
|
|
super().__init__(core_pool_size)
|
|
|
|
def schedule(self, command, delay, unit):
|
|
future = FutureTask(command)
|
|
seconds = unit.toMillis(delay) / 1000.0
|
|
t = _threading.Timer(seconds, future.run)
|
|
t.daemon = True
|
|
t.start()
|
|
return future
|
|
|
|
def scheduleAtFixedRate(self, command, initial_delay, period, unit):
|
|
seconds = unit.toMillis(period) / 1000.0
|
|
init_sec = unit.toMillis(initial_delay) / 1000.0
|
|
def _run():
|
|
_time.sleep(init_sec)
|
|
while True:
|
|
command.run()
|
|
_time.sleep(seconds)
|
|
t = _threading.Thread(target=_run, daemon=True)
|
|
t.start()
|
|
return FutureTask(command)
|
|
|
|
def scheduleWithFixedDelay(self, command, initial_delay, delay, unit):
|
|
return self.scheduleAtFixedRate(command, initial_delay, delay, unit)
|
|
|
|
|
|
class ExecutorCompletionService(CompletionService):
|
|
def __init__(self, executor):
|
|
super().__init__()
|
|
self._executor = executor
|
|
self._queue = _queue.Queue()
|
|
|
|
def submit(self, task):
|
|
future = self._executor.submit(task)
|
|
self._queue.put(future)
|
|
return future
|
|
|
|
def take(self):
|
|
return self._queue.get()
|
|
|
|
def poll(self, timeout=0, unit=None):
|
|
if unit is not None:
|
|
sec = unit.toMillis(timeout) / 1000.0
|
|
else:
|
|
sec = timeout
|
|
try:
|
|
return self._queue.get(timeout=sec)
|
|
except _queue.Empty:
|
|
return None
|
|
|
|
|
|
# ============================================================
|
|
# TimeUnit
|
|
# ============================================================
|
|
|
|
class TimeUnit(Stub):
|
|
NANOSECONDS = None
|
|
MICROSECONDS = None
|
|
MILLISECONDS = None
|
|
SECONDS = None
|
|
MINUTES = None
|
|
HOURS = None
|
|
DAYS = None
|
|
|
|
def __init__(self, name, scale):
|
|
self._name = name
|
|
self._scale = scale # nanos per unit
|
|
|
|
def convert(self, source_duration, source_unit):
|
|
return int(source_duration * source_unit._scale / self._scale)
|
|
|
|
def toNanos(self, duration):
|
|
return int(duration * self._scale)
|
|
|
|
def toMicros(self, duration):
|
|
return int(duration * self._scale // 1000)
|
|
|
|
def toMillis(self, duration):
|
|
return int(duration * self._scale // 1_000_000)
|
|
|
|
def toSeconds(self, duration):
|
|
return int(duration * self._scale // 1_000_000_000)
|
|
|
|
def toMinutes(self, duration):
|
|
return self.toSeconds(duration) // 60
|
|
|
|
def toHours(self, duration):
|
|
return self.toMinutes(duration) // 60
|
|
|
|
def toDays(self, duration):
|
|
return self.toHours(duration) // 24
|
|
|
|
def sleep(self, timeout):
|
|
_time.sleep(self.toMillis(timeout) / 1000.0)
|
|
|
|
def timedJoin(self, thread, timeout):
|
|
thread.join(self.toMillis(timeout) / 1000.0)
|
|
|
|
def timedWait(self, obj, timeout):
|
|
return True
|
|
|
|
def toString(self):
|
|
return self._name
|
|
|
|
|
|
TimeUnit.NANOSECONDS = TimeUnit("NANOSECONDS", 1)
|
|
TimeUnit.MICROSECONDS = TimeUnit("MICROSECONDS", 1000)
|
|
TimeUnit.MILLISECONDS = TimeUnit("MILLISECONDS", 1_000_000)
|
|
TimeUnit.SECONDS = TimeUnit("SECONDS", 1_000_000_000)
|
|
TimeUnit.MINUTES = TimeUnit("MINUTES", 60_000_000_000)
|
|
TimeUnit.HOURS = TimeUnit("HOURS", 3_600_000_000_000)
|
|
TimeUnit.DAYS = TimeUnit("DAYS", 86_400_000_000_000)
|
|
|
|
|
|
# ============================================================
|
|
# CountDownLatch
|
|
# ============================================================
|
|
|
|
class CountDownLatch(Stub):
|
|
def __init__(self, count):
|
|
super().__init__()
|
|
self._count = count
|
|
self._condition = _threading.Condition()
|
|
|
|
def await_(self, timeout=None, unit=None):
|
|
with self._condition:
|
|
if self._count == 0:
|
|
return True
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
self._condition.wait(timeout=seconds)
|
|
return self._count == 0
|
|
self._condition.wait()
|
|
return True
|
|
|
|
def countDown(self):
|
|
with self._condition:
|
|
if self._count > 0:
|
|
self._count -= 1
|
|
if self._count == 0:
|
|
self._condition.notify_all()
|
|
|
|
def getCount(self):
|
|
return self._count
|
|
|
|
def toString(self):
|
|
return f"CountDownLatch(count={self._count})"
|
|
|
|
|
|
# ============================================================
|
|
# CyclicBarrier
|
|
# ============================================================
|
|
|
|
class CyclicBarrier(Stub):
|
|
def __init__(self, parties, barrier_action=None):
|
|
super().__init__()
|
|
self._parties = parties
|
|
self._barrier_action = barrier_action
|
|
self._count = parties
|
|
self._broken = False
|
|
self._lock = _threading.RLock()
|
|
self._condition = _threading.Condition()
|
|
|
|
def await_(self, timeout=None, unit=None):
|
|
with self._condition:
|
|
if self._broken:
|
|
raise BrokenBarrierException()
|
|
self._count -= 1
|
|
if self._count == 0:
|
|
if self._barrier_action:
|
|
try:
|
|
self._barrier_action.run()
|
|
except Exception:
|
|
self._broken = True
|
|
self._condition.notify_all()
|
|
raise BrokenBarrierException()
|
|
self._count = self._parties
|
|
self._condition.notify_all()
|
|
return 0
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
self._condition.wait(timeout=seconds)
|
|
if self._count > 0:
|
|
self._broken = True
|
|
raise BrokenBarrierException()
|
|
else:
|
|
self._condition.wait()
|
|
return self._count
|
|
|
|
def getNumberWaiting(self):
|
|
return self._parties - self._count
|
|
|
|
def getParties(self):
|
|
return self._parties
|
|
|
|
def isBroken(self):
|
|
return self._broken
|
|
|
|
def reset(self):
|
|
with self._condition:
|
|
self._broken = False
|
|
self._count = self._parties
|
|
self._condition.notify_all()
|
|
|
|
|
|
# ============================================================
|
|
# Semaphore
|
|
# ============================================================
|
|
|
|
class Semaphore(Stub):
|
|
def __init__(self, permits, fair=False):
|
|
super().__init__()
|
|
self._sem = _threading.Semaphore(permits) if not fair else _threading.Semaphore(permits)
|
|
self._fair = fair
|
|
self._permits = permits
|
|
self._lock = _threading.Lock()
|
|
|
|
def acquire(self):
|
|
self._sem.acquire()
|
|
|
|
def acquireUninterruptibly(self):
|
|
self._sem.acquire()
|
|
|
|
def release(self):
|
|
self._sem.release()
|
|
|
|
def tryAcquire(self, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
return self._sem.acquire(blocking=True, timeout=seconds)
|
|
return self._sem.acquire(blocking=False)
|
|
|
|
def availablePermits(self):
|
|
return self._sem._value
|
|
|
|
def drainPermits(self):
|
|
with self._lock:
|
|
val = self._sem._value
|
|
for _ in range(val):
|
|
self._sem.acquire(blocking=False)
|
|
return val
|
|
|
|
def getQueueLength(self):
|
|
return 0
|
|
|
|
def hasQueuedThreads(self):
|
|
return False
|
|
|
|
|
|
# ============================================================
|
|
# Phaser (stub)
|
|
# ============================================================
|
|
|
|
class Phaser(Stub):
|
|
def __init__(self, parties=0):
|
|
super().__init__()
|
|
self._parties = parties
|
|
self._phase = 0
|
|
self._arrived = 0
|
|
|
|
def register(self):
|
|
self._parties += 1
|
|
|
|
def arrive(self):
|
|
self._arrived += 1
|
|
return self._phase
|
|
|
|
def arriveAndDeregister(self):
|
|
self._arrived += 1
|
|
self._parties -= 1
|
|
return self._phase
|
|
|
|
def arriveAndAwaitAdvance(self):
|
|
self._arrived += 1
|
|
if self._arrived >= self._parties:
|
|
self._phase += 1
|
|
self._arrived = 0
|
|
return self._phase
|
|
|
|
def awaitAdvance(self, phase):
|
|
return self._phase
|
|
|
|
def getPhase(self):
|
|
return self._phase
|
|
|
|
def getArrivedParties(self):
|
|
return self._arrived
|
|
|
|
def getRegisteredParties(self):
|
|
return self._parties
|
|
|
|
def getUnarrivedParties(self):
|
|
return self._parties - self._arrived
|
|
|
|
def isTerminated(self):
|
|
return False
|
|
|
|
def forceTermination(self):
|
|
pass
|
|
|
|
|
|
# ============================================================
|
|
# Exchanger
|
|
# ============================================================
|
|
|
|
class Exchanger(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._lock = _threading.Lock()
|
|
self._item = None
|
|
self._other_ready = _threading.Event()
|
|
|
|
def exchange(self, x, timeout=None, unit=None):
|
|
with self._lock:
|
|
if self._item is None:
|
|
self._item = x
|
|
self._other_ready.set()
|
|
else:
|
|
result = self._item
|
|
self._item = x
|
|
self._other_ready.set()
|
|
return result
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
self._other_ready.wait(timeout=seconds)
|
|
else:
|
|
self._other_ready.wait()
|
|
with self._lock:
|
|
result = self._item
|
|
self._item = None
|
|
return result
|
|
|
|
|
|
# ============================================================
|
|
# ConcurrentHashMap
|
|
# ============================================================
|
|
|
|
class ConcurrentHashMap(Stub):
|
|
def __init__(self, initial_capacity=16):
|
|
super().__init__()
|
|
self._map = {}
|
|
self._lock = _threading.RLock()
|
|
|
|
def put(self, key, value):
|
|
with self._lock:
|
|
self._map[key] = value
|
|
return None
|
|
|
|
def get(self, key):
|
|
with self._lock:
|
|
return self._map.get(key)
|
|
|
|
def containsKey(self, key):
|
|
with self._lock:
|
|
return key in self._map
|
|
|
|
def containsValue(self, value):
|
|
with self._lock:
|
|
return value in self._map.values()
|
|
|
|
def size(self):
|
|
with self._lock:
|
|
return len(self._map)
|
|
|
|
def isEmpty(self):
|
|
with self._lock:
|
|
return len(self._map) == 0
|
|
|
|
def remove(self, key):
|
|
with self._lock:
|
|
return self._map.pop(key, None)
|
|
|
|
def clear(self):
|
|
with self._lock:
|
|
self._map.clear()
|
|
|
|
def keySet(self):
|
|
with self._lock:
|
|
return set(self._map.keys())
|
|
|
|
def values(self):
|
|
with self._lock:
|
|
return list(self._map.values())
|
|
|
|
def entrySet(self):
|
|
with self._lock:
|
|
return set(self._map.items())
|
|
|
|
def putAll(self, m):
|
|
with self._lock:
|
|
if hasattr(m, "_map"):
|
|
self._map.update(m._map)
|
|
elif isinstance(m, dict):
|
|
self._map.update(m)
|
|
|
|
def putIfAbsent(self, key, value):
|
|
with self._lock:
|
|
if key not in self._map:
|
|
self._map[key] = value
|
|
return None
|
|
return self._map[key]
|
|
|
|
def getOrDefault(self, key, default):
|
|
with self._lock:
|
|
return self._map.get(key, default)
|
|
|
|
def forEach(self, action):
|
|
with self._lock:
|
|
for k, v in self._map.items():
|
|
action(k, v)
|
|
|
|
|
|
# ============================================================
|
|
# CopyOnWriteArrayList / CopyOnWriteArraySet
|
|
# ============================================================
|
|
|
|
class CopyOnWriteArrayList(Stub):
|
|
def __init__(self, *args):
|
|
super().__init__()
|
|
self._list = []
|
|
self._lock = _threading.RLock()
|
|
if args and isinstance(args[0], (list, tuple)):
|
|
self._list = list(args[0])
|
|
|
|
def add(self, e):
|
|
with self._lock:
|
|
self._list = list(self._list)
|
|
self._list.append(e)
|
|
return True
|
|
|
|
def get(self, index):
|
|
return self._list[index]
|
|
|
|
def set(self, index, element):
|
|
with self._lock:
|
|
old = self._list[index]
|
|
self._list = list(self._list)
|
|
self._list[index] = element
|
|
return old
|
|
|
|
def remove(self, e):
|
|
with self._lock:
|
|
new_list = list(self._list)
|
|
try:
|
|
new_list.remove(e)
|
|
self._list = new_list
|
|
return True
|
|
except ValueError:
|
|
return False
|
|
|
|
def size(self):
|
|
return len(self._list)
|
|
|
|
def isEmpty(self):
|
|
return len(self._list) == 0
|
|
|
|
def contains(self, e):
|
|
return e in self._list
|
|
|
|
def iterator(self):
|
|
return iter(list(self._list))
|
|
|
|
def toArray(self):
|
|
return list(self._list)
|
|
|
|
def clear(self):
|
|
with self._lock:
|
|
self._list = []
|
|
|
|
|
|
class CopyOnWriteArraySet(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._backend = CopyOnWriteArrayList()
|
|
|
|
def add(self, e):
|
|
if self._backend.contains(e):
|
|
return False
|
|
return self._backend.add(e)
|
|
|
|
def remove(self, e):
|
|
return self._backend.remove(e)
|
|
|
|
def contains(self, e):
|
|
return self._backend.contains(e)
|
|
|
|
def size(self):
|
|
return self._backend.size()
|
|
|
|
def isEmpty(self):
|
|
return self._backend.isEmpty()
|
|
|
|
def iterator(self):
|
|
return self._backend.iterator()
|
|
|
|
|
|
# ============================================================
|
|
# BlockingQueue / LinkedBlockingQueue / ArrayBlockingQueue
|
|
# ============================================================
|
|
|
|
class BlockingQueue(Stub):
|
|
pass
|
|
|
|
|
|
class LinkedBlockingQueue(BlockingQueue):
|
|
def __init__(self, capacity=None):
|
|
super().__init__()
|
|
self._queue = _queue.Queue(maxsize=capacity if capacity else 0)
|
|
|
|
def put(self, item):
|
|
self._queue.put(item)
|
|
|
|
def take(self):
|
|
return self._queue.get()
|
|
|
|
def offer(self, item, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
try:
|
|
self._queue.put(item, timeout=seconds)
|
|
return True
|
|
except _queue.Full:
|
|
return False
|
|
try:
|
|
self._queue.put_nowait(item)
|
|
return True
|
|
except _queue.Full:
|
|
return False
|
|
|
|
def poll(self, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
try:
|
|
return self._queue.get(timeout=seconds)
|
|
except _queue.Empty:
|
|
return None
|
|
try:
|
|
return self._queue.get_nowait()
|
|
except _queue.Empty:
|
|
return None
|
|
|
|
def size(self):
|
|
return self._queue.qsize()
|
|
|
|
def isEmpty(self):
|
|
return self._queue.empty()
|
|
|
|
def remainingCapacity(self):
|
|
return self._queue.maxsize - self._queue.qsize()
|
|
|
|
def clear(self):
|
|
while not self._queue.empty():
|
|
try:
|
|
self._queue.get_nowait()
|
|
except _queue.Empty:
|
|
break
|
|
|
|
def contains(self, item):
|
|
return item in list(self._queue.queue)
|
|
|
|
|
|
class ArrayBlockingQueue(LinkedBlockingQueue):
|
|
def __init__(self, capacity, fair=False):
|
|
super().__init__(capacity)
|
|
|
|
|
|
class PriorityBlockingQueue(BlockingQueue):
|
|
def __init__(self, capacity=None):
|
|
super().__init__()
|
|
self._heap = []
|
|
self._lock = _threading.RLock()
|
|
self._not_empty = _threading.Condition(self._lock)
|
|
|
|
def put(self, item):
|
|
with self._lock:
|
|
_queue.heappush(self._heap, item)
|
|
self._not_empty.notify()
|
|
|
|
def take(self):
|
|
with self._lock:
|
|
while not self._heap:
|
|
self._not_empty.wait()
|
|
return _queue.heappop(self._heap)
|
|
|
|
def offer(self, item, timeout=None, unit=None):
|
|
self.put(item)
|
|
return True
|
|
|
|
def poll(self, timeout=None, unit=None):
|
|
with self._lock:
|
|
if not self._heap:
|
|
return None
|
|
return _queue.heappop(self._heap)
|
|
|
|
def size(self):
|
|
with self._lock:
|
|
return len(self._heap)
|
|
|
|
def isEmpty(self):
|
|
with self._lock:
|
|
return len(self._heap) == 0
|
|
|
|
def clear(self):
|
|
with self._lock:
|
|
self._heap = []
|
|
|
|
|
|
class SynchronousQueue(BlockingQueue):
|
|
def __init__(self, fair=False):
|
|
super().__init__()
|
|
self._exchange = _queue.Queue(maxsize=1)
|
|
|
|
def put(self, item):
|
|
self._exchange.put(item)
|
|
|
|
def take(self):
|
|
return self._exchange.get()
|
|
|
|
def offer(self, item, timeout=None, unit=None):
|
|
try:
|
|
self._exchange.put_nowait(item)
|
|
return True
|
|
except _queue.Full:
|
|
return False
|
|
|
|
def poll(self, timeout=None, unit=None):
|
|
try:
|
|
return self._exchange.get_nowait()
|
|
except _queue.Empty:
|
|
return None
|
|
|
|
|
|
class DelayQueue(BlockingQueue):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._queue = []
|
|
|
|
def put(self, item):
|
|
_queue.heappush(self._queue, item)
|
|
|
|
def take(self):
|
|
while True:
|
|
if self._queue:
|
|
item = self._queue[0]
|
|
delay = item.getDelay(TimeUnit.MILLISECONDS)
|
|
if delay <= 0:
|
|
return _queue.heappop(self._queue)
|
|
_time.sleep(delay / 1000.0)
|
|
else:
|
|
_time.sleep(0.1)
|
|
|
|
|
|
class ConcurrentLinkedQueue(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._queue = _queue.Queue()
|
|
|
|
def add(self, item):
|
|
self._queue.put(item)
|
|
return True
|
|
|
|
def offer(self, item):
|
|
self._queue.put_nowait(item)
|
|
return True
|
|
|
|
def poll(self):
|
|
try:
|
|
return self._queue.get_nowait()
|
|
except _queue.Empty:
|
|
return None
|
|
|
|
def peek(self):
|
|
try:
|
|
item = self._queue.get_nowait()
|
|
self._queue.put_nowait(item)
|
|
return item
|
|
except _queue.Empty:
|
|
return None
|
|
|
|
def size(self):
|
|
return self._queue.qsize()
|
|
|
|
def isEmpty(self):
|
|
return self._queue.empty()
|
|
|
|
def contains(self, item):
|
|
return item in list(self._queue.queue)
|
|
|
|
|
|
class ConcurrentLinkedDeque(ConcurrentLinkedQueue):
|
|
def addFirst(self, item):
|
|
self._queue.put(item)
|
|
|
|
def addLast(self, item):
|
|
self._queue.put(item)
|
|
|
|
def pollFirst(self):
|
|
return self.poll()
|
|
|
|
def pollLast(self):
|
|
return self.poll()
|
|
|
|
|
|
class BlockingDeque(BlockingQueue):
|
|
pass
|
|
|
|
|
|
# ============================================================
|
|
# Atomic classes
|
|
# ============================================================
|
|
|
|
class AtomicBoolean(Stub):
|
|
def __init__(self, initial=False):
|
|
super().__init__()
|
|
self._value = initial
|
|
self._lock = _threading.Lock()
|
|
|
|
def get(self):
|
|
with self._lock:
|
|
return self._value
|
|
|
|
def set(self, new_value):
|
|
with self._lock:
|
|
self._value = new_value
|
|
|
|
def compareAndSet(self, expect, update):
|
|
with self._lock:
|
|
if self._value == expect:
|
|
self._value = update
|
|
return True
|
|
return False
|
|
|
|
def getAndSet(self, new_value):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value = new_value
|
|
return old
|
|
|
|
def toString(self):
|
|
return str(self._value)
|
|
|
|
|
|
class AtomicInteger(Stub):
|
|
def __init__(self, initial=0):
|
|
super().__init__()
|
|
self._value = int(initial)
|
|
self._lock = _threading.Lock()
|
|
|
|
def get(self):
|
|
with self._lock:
|
|
return self._value
|
|
|
|
def set(self, new_value):
|
|
with self._lock:
|
|
self._value = int(new_value)
|
|
|
|
def getAndSet(self, new_value):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value = int(new_value)
|
|
return old
|
|
|
|
def compareAndSet(self, expect, update):
|
|
with self._lock:
|
|
if self._value == expect:
|
|
self._value = int(update)
|
|
return True
|
|
return False
|
|
|
|
def weakCompareAndSet(self, expect, update):
|
|
return self.compareAndSet(expect, update)
|
|
|
|
def getAndIncrement(self):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value += 1
|
|
return old
|
|
|
|
def getAndDecrement(self):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value -= 1
|
|
return old
|
|
|
|
def getAndAdd(self, delta):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value += delta
|
|
return old
|
|
|
|
def incrementAndGet(self):
|
|
with self._lock:
|
|
self._value += 1
|
|
return self._value
|
|
|
|
def decrementAndGet(self):
|
|
with self._lock:
|
|
self._value -= 1
|
|
return self._value
|
|
|
|
def addAndGet(self, delta):
|
|
with self._lock:
|
|
self._value += delta
|
|
return self._value
|
|
|
|
def lazySet(self, new_value):
|
|
with self._lock:
|
|
self._value = int(new_value)
|
|
|
|
def updateAndGet(self, func):
|
|
with self._lock:
|
|
self._value = func(self._value)
|
|
return self._value
|
|
|
|
def accumulateAndGet(self, x, func):
|
|
with self._lock:
|
|
self._value = func(self._value, x)
|
|
return self._value
|
|
|
|
def intValue(self):
|
|
return self.get()
|
|
|
|
def longValue(self):
|
|
return self.get()
|
|
|
|
def floatValue(self):
|
|
return float(self.get())
|
|
|
|
def doubleValue(self):
|
|
return float(self.get())
|
|
|
|
def toString(self):
|
|
return str(self._value)
|
|
|
|
|
|
class AtomicLong(AtomicInteger):
|
|
pass
|
|
|
|
|
|
class AtomicReference(Stub):
|
|
def __init__(self, initial=None):
|
|
super().__init__()
|
|
self._value = initial
|
|
self._lock = _threading.Lock()
|
|
|
|
def get(self):
|
|
with self._lock:
|
|
return self._value
|
|
|
|
def set(self, new_value):
|
|
with self._lock:
|
|
self._value = new_value
|
|
|
|
def compareAndSet(self, expect, update):
|
|
with self._lock:
|
|
if self._value == expect:
|
|
self._value = update
|
|
return True
|
|
return False
|
|
|
|
def getAndSet(self, new_value):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value = new_value
|
|
return old
|
|
|
|
def getAndUpdate(self, func):
|
|
with self._lock:
|
|
old = self._value
|
|
self._value = func(old)
|
|
return old
|
|
|
|
def updateAndGet(self, func):
|
|
with self._lock:
|
|
self._value = func(self._value)
|
|
return self._value
|
|
|
|
def accumulateAndGet(self, x, func):
|
|
with self._lock:
|
|
self._value = func(self._value, x)
|
|
return self._value
|
|
|
|
|
|
class AtomicIntegerArray(Stub):
|
|
def __init__(self, length_or_array):
|
|
super().__init__()
|
|
if isinstance(length_or_array, int):
|
|
self._array = [0] * length_or_array
|
|
else:
|
|
self._array = list(length_or_array)
|
|
|
|
def get(self, i):
|
|
return self._array[i]
|
|
|
|
def set(self, i, new_value):
|
|
self._array[i] = new_value
|
|
|
|
def compareAndSet(self, i, expect, update):
|
|
if self._array[i] == expect:
|
|
self._array[i] = update
|
|
return True
|
|
return False
|
|
|
|
def getAndAdd(self, i, delta):
|
|
old = self._array[i]
|
|
self._array[i] += delta
|
|
return old
|
|
|
|
def addAndGet(self, i, delta):
|
|
self._array[i] += delta
|
|
return self._array[i]
|
|
|
|
def length(self):
|
|
return len(self._array)
|
|
|
|
|
|
class AtomicLongArray(AtomicIntegerArray):
|
|
pass
|
|
|
|
|
|
class AtomicReferenceArray(Stub):
|
|
def __init__(self, length_or_array):
|
|
super().__init__()
|
|
if isinstance(length_or_array, int):
|
|
self._array = [None] * length_or_array
|
|
else:
|
|
self._array = list(length_or_array)
|
|
|
|
def get(self, i):
|
|
return self._array[i]
|
|
|
|
def set(self, i, new_value):
|
|
self._array[i] = new_value
|
|
|
|
def compareAndSet(self, i, expect, update):
|
|
if self._array[i] == expect:
|
|
self._array[i] = update
|
|
return True
|
|
return False
|
|
|
|
def length(self):
|
|
return len(self._array)
|
|
|
|
|
|
class AtomicIntegerFieldUpdater(Stub):
|
|
@staticmethod
|
|
def newUpdater(tclass, field_name):
|
|
return AtomicIntegerFieldUpdater()
|
|
|
|
def get(self, obj):
|
|
return 0
|
|
|
|
def set(self, obj, new_value):
|
|
pass
|
|
|
|
def compareAndSet(self, obj, expect, update):
|
|
return True
|
|
|
|
|
|
class AtomicLongFieldUpdater(AtomicIntegerFieldUpdater):
|
|
pass
|
|
|
|
|
|
class AtomicReferenceFieldUpdater(Stub):
|
|
@staticmethod
|
|
def newUpdater(tclass, vclass, field_name):
|
|
return AtomicReferenceFieldUpdater()
|
|
|
|
def get(self, obj):
|
|
return None
|
|
|
|
def set(self, obj, new_value):
|
|
pass
|
|
|
|
def compareAndSet(self, obj, expect, update):
|
|
return True
|
|
|
|
|
|
class AtomicMarkableReference(Stub):
|
|
def __init__(self, initial_ref, initial_mark):
|
|
super().__init__()
|
|
self._ref = initial_ref
|
|
self._mark = initial_mark
|
|
|
|
def getReference(self):
|
|
return self._ref
|
|
|
|
def isMarked(self):
|
|
return self._mark
|
|
|
|
def compareAndSet(self, expected_ref, new_ref, expected_mark, new_mark):
|
|
if self._ref == expected_ref and self._mark == expected_mark:
|
|
self._ref = new_ref
|
|
self._mark = new_mark
|
|
return True
|
|
return False
|
|
|
|
def attemptMark(self, expected_ref, new_mark):
|
|
if self._ref == expected_ref:
|
|
self._mark = new_mark
|
|
return True
|
|
return False
|
|
|
|
|
|
class AtomicStampedReference(Stub):
|
|
def __init__(self, initial_ref, initial_stamp):
|
|
super().__init__()
|
|
self._ref = initial_ref
|
|
self._stamp = initial_stamp
|
|
|
|
def getReference(self):
|
|
return self._ref
|
|
|
|
def getStamp(self):
|
|
return self._stamp
|
|
|
|
def compareAndSet(self, expected_ref, new_ref, expected_stamp, new_stamp):
|
|
if self._ref == expected_ref and self._stamp == expected_stamp:
|
|
self._ref = new_ref
|
|
self._stamp = new_stamp
|
|
return True
|
|
return False
|
|
|
|
def attemptStamp(self, expected_ref, new_stamp):
|
|
if self._ref == expected_ref:
|
|
self._stamp = new_stamp
|
|
return True
|
|
return False
|
|
|
|
def set(self, new_ref, new_stamp):
|
|
self._ref = new_ref
|
|
self._stamp = new_stamp
|
|
|
|
|
|
class DoubleAccumulator(Stub):
|
|
def __init__(self, accumulator_function, identity):
|
|
super().__init__()
|
|
self._value = identity
|
|
self._func = accumulator_function
|
|
|
|
def accumulate(self, x):
|
|
self._value = self._func(self._value, x)
|
|
|
|
def get(self):
|
|
return self._value
|
|
|
|
def reset(self):
|
|
self._value = 0.0
|
|
|
|
|
|
class DoubleAdder(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._value = 0.0
|
|
|
|
def add(self, x):
|
|
self._value += x
|
|
|
|
def sum(self):
|
|
return self._value
|
|
|
|
def reset(self):
|
|
self._value = 0.0
|
|
|
|
def doubleValue(self):
|
|
return self._value
|
|
|
|
def toString(self):
|
|
return str(self._value)
|
|
|
|
|
|
class LongAccumulator(Stub):
|
|
def __init__(self, accumulator_function, identity):
|
|
super().__init__()
|
|
self._value = identity
|
|
self._func = accumulator_function
|
|
|
|
def accumulate(self, x):
|
|
self._value = self._func(self._value, x)
|
|
|
|
def get(self):
|
|
return self._value
|
|
|
|
def reset(self):
|
|
self._value = 0
|
|
|
|
|
|
class LongAdder(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._value = 0
|
|
|
|
def add(self, x):
|
|
self._value += x
|
|
|
|
def sum(self):
|
|
return self._value
|
|
|
|
def reset(self):
|
|
self._value = 0
|
|
|
|
def intValue(self):
|
|
return self._value
|
|
|
|
def longValue(self):
|
|
return self._value
|
|
|
|
def toString(self):
|
|
return str(self._value)
|
|
|
|
|
|
# ============================================================
|
|
# ReentrantLock
|
|
# ============================================================
|
|
|
|
class Lock(Stub):
|
|
def lock(self):
|
|
raise NotImplementedError
|
|
|
|
def lockInterruptibly(self):
|
|
raise NotImplementedError
|
|
|
|
def tryLock(self, timeout=None, unit=None):
|
|
raise NotImplementedError
|
|
|
|
def unlock(self):
|
|
raise NotImplementedError
|
|
|
|
def newCondition(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class ReentrantLock(Lock):
|
|
def __init__(self, fair=False):
|
|
super().__init__()
|
|
self._lock = _threading.RLock() if not fair else _threading.RLock()
|
|
|
|
def lock(self):
|
|
self._lock.acquire()
|
|
|
|
def lockInterruptibly(self):
|
|
self._lock.acquire()
|
|
|
|
def tryLock(self, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
return self._lock.acquire(timeout=seconds)
|
|
return self._lock.acquire(blocking=False)
|
|
|
|
def unlock(self):
|
|
self._lock.release()
|
|
|
|
def newCondition(self):
|
|
return Condition()
|
|
|
|
def getHoldCount(self):
|
|
return 1 if self._lock._is_owned() else 0
|
|
|
|
def isHeldByCurrentThread(self):
|
|
return self._lock._is_owned()
|
|
|
|
def isLocked(self):
|
|
return True
|
|
|
|
def getQueueLength(self):
|
|
return 0
|
|
|
|
def hasQueuedThreads(self):
|
|
return False
|
|
|
|
def getOwner(self):
|
|
return _threading.current_thread() if self.isHeldByCurrentThread() else None
|
|
|
|
|
|
# ============================================================
|
|
# ReadWriteLock
|
|
# ============================================================
|
|
|
|
class ReadWriteLock(Stub):
|
|
def readLock(self):
|
|
raise NotImplementedError
|
|
|
|
def writeLock(self):
|
|
raise NotImplementedError
|
|
|
|
|
|
class ReentrantReadWriteLock(ReadWriteLock):
|
|
class ReadLock(Lock):
|
|
def __init__(self, rw_lock):
|
|
super().__init__()
|
|
self._rw_lock = rw_lock
|
|
|
|
def lock(self):
|
|
self._rw_lock._read_lock.acquire()
|
|
|
|
def unlock(self):
|
|
self._rw_lock._read_lock.release()
|
|
|
|
def tryLock(self, timeout=None, unit=None):
|
|
return self._rw_lock._read_lock.acquire(blocking=False)
|
|
|
|
class WriteLock(Lock):
|
|
def __init__(self, rw_lock):
|
|
super().__init__()
|
|
self._rw_lock = rw_lock
|
|
|
|
def lock(self):
|
|
self._rw_lock._write_lock.acquire()
|
|
|
|
def unlock(self):
|
|
self._rw_lock._write_lock.release()
|
|
|
|
def tryLock(self, timeout=None, unit=None):
|
|
return self._rw_lock._write_lock.acquire(blocking=False)
|
|
|
|
def __init__(self, fair=False):
|
|
super().__init__()
|
|
self._read_lock_obj = _threading.RLock()
|
|
self._write_lock_obj = _threading.Lock()
|
|
self._read_lock = ReentrantReadWriteLock.ReadLock(self)
|
|
self._write_lock = ReentrantReadWriteLock.WriteLock(self)
|
|
|
|
def readLock(self):
|
|
return self._read_lock
|
|
|
|
def writeLock(self):
|
|
return self._write_lock
|
|
|
|
|
|
class Condition(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._cond = _threading.Condition()
|
|
|
|
def await_(self, timeout=None, unit=None):
|
|
if timeout is not None and unit is not None:
|
|
seconds = unit.toMillis(timeout) / 1000.0
|
|
with self._cond:
|
|
return self._cond.wait(timeout=seconds)
|
|
with self._cond:
|
|
self._cond.wait()
|
|
|
|
def awaitUninterruptibly(self):
|
|
with self._cond:
|
|
self._cond.wait()
|
|
|
|
def awaitNanos(self, nanos_timeout):
|
|
seconds = nanos_timeout / 1_000_000_000.0
|
|
with self._cond:
|
|
self._cond.wait(timeout=seconds)
|
|
return 0
|
|
|
|
def awaitUntil(self, deadline):
|
|
remaining = (deadline - _time.time()) * 1000
|
|
if remaining > 0:
|
|
self.await_(remaining, TimeUnit.MILLISECONDS)
|
|
|
|
def signal(self):
|
|
with self._cond:
|
|
self._cond.notify()
|
|
|
|
def signalAll(self):
|
|
with self._cond:
|
|
self._cond.notify_all()
|
|
|
|
|
|
class LockSupport(Stub):
|
|
@staticmethod
|
|
def park():
|
|
_time.sleep(1)
|
|
|
|
@staticmethod
|
|
def parkNanos(nanos):
|
|
_time.sleep(nanos / 1_000_000_000.0)
|
|
|
|
@staticmethod
|
|
def parkUntil(deadline):
|
|
remaining = deadline - _time.time()
|
|
if remaining > 0:
|
|
_time.sleep(remaining)
|
|
|
|
@staticmethod
|
|
def unpark(thread):
|
|
pass
|
|
|
|
|
|
# ============================================================
|
|
# AbstractQueuedSynchronizer (stubs)
|
|
# ============================================================
|
|
|
|
class AbstractQueuedSynchronizer(Stub):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._state = 0
|
|
|
|
def getState(self):
|
|
return self._state
|
|
|
|
def setState(self, state):
|
|
self._state = state
|
|
|
|
def compareAndSetState(self, expect, update):
|
|
if self._state == expect:
|
|
self._state = update
|
|
return True
|
|
return False
|
|
|
|
def acquire(self, arg):
|
|
pass
|
|
|
|
def acquireInterruptibly(self, arg):
|
|
pass
|
|
|
|
def tryAcquire(self, arg):
|
|
return True
|
|
|
|
def tryRelease(self, arg):
|
|
return True
|
|
|
|
def release(self, arg):
|
|
return True
|
|
|
|
def acquireShared(self, arg):
|
|
pass
|
|
|
|
def releaseShared(self, arg):
|
|
return True
|
|
|
|
def tryAcquireShared(self, arg):
|
|
return 0
|
|
|
|
def tryReleaseShared(self, arg):
|
|
return True
|
|
|
|
def hasQueuedThreads(self):
|
|
return False
|
|
|
|
def getQueueLength(self):
|
|
return 0
|
|
|
|
|
|
class AbstractQueuedLongSynchronizer(AbstractQueuedSynchronizer):
|
|
pass
|
|
|
|
|
|
# ============================================================
|
|
# Flow / SubmissionPublisher (stubs)
|
|
# ============================================================
|
|
|
|
class Flow(Stub):
|
|
class Publisher(Stub):
|
|
def subscribe(self, subscriber):
|
|
pass
|
|
|
|
class Subscriber(Stub):
|
|
def onSubscribe(self, subscription):
|
|
pass
|
|
|
|
def onNext(self, item):
|
|
pass
|
|
|
|
def onError(self, throwable):
|
|
pass
|
|
|
|
def onComplete(self):
|
|
pass
|
|
|
|
class Subscription(Stub):
|
|
def request(self, n):
|
|
pass
|
|
|
|
def cancel(self):
|
|
pass
|
|
|
|
class Processor(Stub):
|
|
pass
|
|
|
|
|
|
class SubmissionPublisher(Flow.Publisher):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self._subscribers = []
|
|
|
|
def subscribe(self, subscriber):
|
|
self._subscribers.append(subscriber)
|
|
|
|
def submit(self, item):
|
|
for sub in self._subscribers:
|
|
sub.onNext(item)
|
|
return 1
|
|
|
|
def close(self):
|
|
for sub in self._subscribers:
|
|
sub.onComplete()
|
|
|
|
|
|
# ============================================================
|
|
# ForkJoinPool / ForkJoinTask (stubs)
|
|
# ============================================================
|
|
|
|
class ForkJoinPool(Stub):
|
|
def __init__(self, parallelism=None):
|
|
super().__init__()
|
|
self._parallelism = parallelism or _py_math.ceil(_threading._count / 2)
|
|
self._pool = _futures.ThreadPoolExecutor(max_workers=self._parallelism)
|
|
|
|
def execute(self, task):
|
|
self._pool.submit(task.run)
|
|
|
|
def submit(self, task):
|
|
future = FutureTask(task)
|
|
self._pool.submit(future.run)
|
|
return future
|
|
|
|
def invoke(self, task):
|
|
return task.run()
|
|
|
|
def shutdown(self):
|
|
self._pool.shutdown(wait=False)
|
|
|
|
|
|
class ForkJoinTask(Future):
|
|
def fork(self):
|
|
return self
|
|
|
|
def join(self):
|
|
return None
|
|
|
|
def invoke(self):
|
|
return None
|
|
|
|
def adapt(self, callable_or_runnable):
|
|
return ForkJoinTask()
|
|
|
|
|
|
class RecursiveAction(ForkJoinTask):
|
|
def compute(self):
|
|
raise NotImplementedError
|
|
|
|
def run(self):
|
|
self.compute()
|
|
|
|
|
|
class RecursiveTask(ForkJoinTask):
|
|
def compute(self):
|
|
raise NotImplementedError
|
|
|
|
def run(self):
|
|
self.compute()
|
|
|
|
|
|
class ForkJoinWorkerThread(Stub):
|
|
def __init__(self, pool):
|
|
super().__init__()
|
|
self._pool = pool
|
|
|
|
def getPool(self):
|
|
return self._pool |