""" 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