17db96d56Sopenharmony_ci"""Thread module emulating a subset of Java's threading model.""" 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciimport os as _os 47db96d56Sopenharmony_ciimport sys as _sys 57db96d56Sopenharmony_ciimport _thread 67db96d56Sopenharmony_ciimport functools 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_cifrom time import monotonic as _time 97db96d56Sopenharmony_cifrom _weakrefset import WeakSet 107db96d56Sopenharmony_cifrom itertools import islice as _islice, count as _count 117db96d56Sopenharmony_citry: 127db96d56Sopenharmony_ci from _collections import deque as _deque 137db96d56Sopenharmony_ciexcept ImportError: 147db96d56Sopenharmony_ci from collections import deque as _deque 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci# Note regarding PEP 8 compliant names 177db96d56Sopenharmony_ci# This threading model was originally inspired by Java, and inherited 187db96d56Sopenharmony_ci# the convention of camelCase function and method names from that 197db96d56Sopenharmony_ci# language. Those original names are not in any imminent danger of 207db96d56Sopenharmony_ci# being deprecated (even for Py3k),so this module provides them as an 217db96d56Sopenharmony_ci# alias for the PEP 8 compliant names 227db96d56Sopenharmony_ci# Note that using the new PEP 8 compliant names facilitates substitution 237db96d56Sopenharmony_ci# with the multiprocessing module, which doesn't provide the old 247db96d56Sopenharmony_ci# Java inspired names. 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ci__all__ = ['get_ident', 'active_count', 'Condition', 'current_thread', 277db96d56Sopenharmony_ci 'enumerate', 'main_thread', 'TIMEOUT_MAX', 287db96d56Sopenharmony_ci 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 297db96d56Sopenharmony_ci 'Barrier', 'BrokenBarrierError', 'Timer', 'ThreadError', 307db96d56Sopenharmony_ci 'setprofile', 'settrace', 'local', 'stack_size', 317db96d56Sopenharmony_ci 'excepthook', 'ExceptHookArgs', 'gettrace', 'getprofile'] 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci# Rename some stuff so "from threading import *" is safe 347db96d56Sopenharmony_ci_start_new_thread = _thread.start_new_thread 357db96d56Sopenharmony_ci_allocate_lock = _thread.allocate_lock 367db96d56Sopenharmony_ci_set_sentinel = _thread._set_sentinel 377db96d56Sopenharmony_ciget_ident = _thread.get_ident 387db96d56Sopenharmony_citry: 397db96d56Sopenharmony_ci get_native_id = _thread.get_native_id 407db96d56Sopenharmony_ci _HAVE_THREAD_NATIVE_ID = True 417db96d56Sopenharmony_ci __all__.append('get_native_id') 427db96d56Sopenharmony_ciexcept AttributeError: 437db96d56Sopenharmony_ci _HAVE_THREAD_NATIVE_ID = False 447db96d56Sopenharmony_ciThreadError = _thread.error 457db96d56Sopenharmony_citry: 467db96d56Sopenharmony_ci _CRLock = _thread.RLock 477db96d56Sopenharmony_ciexcept AttributeError: 487db96d56Sopenharmony_ci _CRLock = None 497db96d56Sopenharmony_ciTIMEOUT_MAX = _thread.TIMEOUT_MAX 507db96d56Sopenharmony_cidel _thread 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci# Support for profile and trace hooks 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci_profile_hook = None 567db96d56Sopenharmony_ci_trace_hook = None 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_cidef setprofile(func): 597db96d56Sopenharmony_ci """Set a profile function for all threads started from the threading module. 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci The func will be passed to sys.setprofile() for each thread, before its 627db96d56Sopenharmony_ci run() method is called. 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci """ 657db96d56Sopenharmony_ci global _profile_hook 667db96d56Sopenharmony_ci _profile_hook = func 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_cidef getprofile(): 697db96d56Sopenharmony_ci """Get the profiler function as set by threading.setprofile().""" 707db96d56Sopenharmony_ci return _profile_hook 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_cidef settrace(func): 737db96d56Sopenharmony_ci """Set a trace function for all threads started from the threading module. 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci The func will be passed to sys.settrace() for each thread, before its run() 767db96d56Sopenharmony_ci method is called. 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci """ 797db96d56Sopenharmony_ci global _trace_hook 807db96d56Sopenharmony_ci _trace_hook = func 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_cidef gettrace(): 837db96d56Sopenharmony_ci """Get the trace function as set by threading.settrace().""" 847db96d56Sopenharmony_ci return _trace_hook 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci# Synchronization classes 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ciLock = _allocate_lock 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_cidef RLock(*args, **kwargs): 917db96d56Sopenharmony_ci """Factory function that returns a new reentrant lock. 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci A reentrant lock must be released by the thread that acquired it. Once a 947db96d56Sopenharmony_ci thread has acquired a reentrant lock, the same thread may acquire it again 957db96d56Sopenharmony_ci without blocking; the thread must release it once for each time it has 967db96d56Sopenharmony_ci acquired it. 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci """ 997db96d56Sopenharmony_ci if _CRLock is None: 1007db96d56Sopenharmony_ci return _PyRLock(*args, **kwargs) 1017db96d56Sopenharmony_ci return _CRLock(*args, **kwargs) 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ciclass _RLock: 1047db96d56Sopenharmony_ci """This class implements reentrant lock objects. 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci A reentrant lock must be released by the thread that acquired it. Once a 1077db96d56Sopenharmony_ci thread has acquired a reentrant lock, the same thread may acquire it 1087db96d56Sopenharmony_ci again without blocking; the thread must release it once for each time it 1097db96d56Sopenharmony_ci has acquired it. 1107db96d56Sopenharmony_ci 1117db96d56Sopenharmony_ci """ 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci def __init__(self): 1147db96d56Sopenharmony_ci self._block = _allocate_lock() 1157db96d56Sopenharmony_ci self._owner = None 1167db96d56Sopenharmony_ci self._count = 0 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci def __repr__(self): 1197db96d56Sopenharmony_ci owner = self._owner 1207db96d56Sopenharmony_ci try: 1217db96d56Sopenharmony_ci owner = _active[owner].name 1227db96d56Sopenharmony_ci except KeyError: 1237db96d56Sopenharmony_ci pass 1247db96d56Sopenharmony_ci return "<%s %s.%s object owner=%r count=%d at %s>" % ( 1257db96d56Sopenharmony_ci "locked" if self._block.locked() else "unlocked", 1267db96d56Sopenharmony_ci self.__class__.__module__, 1277db96d56Sopenharmony_ci self.__class__.__qualname__, 1287db96d56Sopenharmony_ci owner, 1297db96d56Sopenharmony_ci self._count, 1307db96d56Sopenharmony_ci hex(id(self)) 1317db96d56Sopenharmony_ci ) 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ci def _at_fork_reinit(self): 1347db96d56Sopenharmony_ci self._block._at_fork_reinit() 1357db96d56Sopenharmony_ci self._owner = None 1367db96d56Sopenharmony_ci self._count = 0 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci def acquire(self, blocking=True, timeout=-1): 1397db96d56Sopenharmony_ci """Acquire a lock, blocking or non-blocking. 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci When invoked without arguments: if this thread already owns the lock, 1427db96d56Sopenharmony_ci increment the recursion level by one, and return immediately. Otherwise, 1437db96d56Sopenharmony_ci if another thread owns the lock, block until the lock is unlocked. Once 1447db96d56Sopenharmony_ci the lock is unlocked (not owned by any thread), then grab ownership, set 1457db96d56Sopenharmony_ci the recursion level to one, and return. If more than one thread is 1467db96d56Sopenharmony_ci blocked waiting until the lock is unlocked, only one at a time will be 1477db96d56Sopenharmony_ci able to grab ownership of the lock. There is no return value in this 1487db96d56Sopenharmony_ci case. 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci When invoked with the blocking argument set to true, do the same thing 1517db96d56Sopenharmony_ci as when called without arguments, and return true. 1527db96d56Sopenharmony_ci 1537db96d56Sopenharmony_ci When invoked with the blocking argument set to false, do not block. If a 1547db96d56Sopenharmony_ci call without an argument would block, return false immediately; 1557db96d56Sopenharmony_ci otherwise, do the same thing as when called without arguments, and 1567db96d56Sopenharmony_ci return true. 1577db96d56Sopenharmony_ci 1587db96d56Sopenharmony_ci When invoked with the floating-point timeout argument set to a positive 1597db96d56Sopenharmony_ci value, block for at most the number of seconds specified by timeout 1607db96d56Sopenharmony_ci and as long as the lock cannot be acquired. Return true if the lock has 1617db96d56Sopenharmony_ci been acquired, false if the timeout has elapsed. 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci """ 1647db96d56Sopenharmony_ci me = get_ident() 1657db96d56Sopenharmony_ci if self._owner == me: 1667db96d56Sopenharmony_ci self._count += 1 1677db96d56Sopenharmony_ci return 1 1687db96d56Sopenharmony_ci rc = self._block.acquire(blocking, timeout) 1697db96d56Sopenharmony_ci if rc: 1707db96d56Sopenharmony_ci self._owner = me 1717db96d56Sopenharmony_ci self._count = 1 1727db96d56Sopenharmony_ci return rc 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci __enter__ = acquire 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci def release(self): 1777db96d56Sopenharmony_ci """Release a lock, decrementing the recursion level. 1787db96d56Sopenharmony_ci 1797db96d56Sopenharmony_ci If after the decrement it is zero, reset the lock to unlocked (not owned 1807db96d56Sopenharmony_ci by any thread), and if any other threads are blocked waiting for the 1817db96d56Sopenharmony_ci lock to become unlocked, allow exactly one of them to proceed. If after 1827db96d56Sopenharmony_ci the decrement the recursion level is still nonzero, the lock remains 1837db96d56Sopenharmony_ci locked and owned by the calling thread. 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci Only call this method when the calling thread owns the lock. A 1867db96d56Sopenharmony_ci RuntimeError is raised if this method is called when the lock is 1877db96d56Sopenharmony_ci unlocked. 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci There is no return value. 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci """ 1927db96d56Sopenharmony_ci if self._owner != get_ident(): 1937db96d56Sopenharmony_ci raise RuntimeError("cannot release un-acquired lock") 1947db96d56Sopenharmony_ci self._count = count = self._count - 1 1957db96d56Sopenharmony_ci if not count: 1967db96d56Sopenharmony_ci self._owner = None 1977db96d56Sopenharmony_ci self._block.release() 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci def __exit__(self, t, v, tb): 2007db96d56Sopenharmony_ci self.release() 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci # Internal methods used by condition variables 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci def _acquire_restore(self, state): 2057db96d56Sopenharmony_ci self._block.acquire() 2067db96d56Sopenharmony_ci self._count, self._owner = state 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_ci def _release_save(self): 2097db96d56Sopenharmony_ci if self._count == 0: 2107db96d56Sopenharmony_ci raise RuntimeError("cannot release un-acquired lock") 2117db96d56Sopenharmony_ci count = self._count 2127db96d56Sopenharmony_ci self._count = 0 2137db96d56Sopenharmony_ci owner = self._owner 2147db96d56Sopenharmony_ci self._owner = None 2157db96d56Sopenharmony_ci self._block.release() 2167db96d56Sopenharmony_ci return (count, owner) 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci def _is_owned(self): 2197db96d56Sopenharmony_ci return self._owner == get_ident() 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci_PyRLock = _RLock 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ciclass Condition: 2257db96d56Sopenharmony_ci """Class that implements a condition variable. 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci A condition variable allows one or more threads to wait until they are 2287db96d56Sopenharmony_ci notified by another thread. 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci If the lock argument is given and not None, it must be a Lock or RLock 2317db96d56Sopenharmony_ci object, and it is used as the underlying lock. Otherwise, a new RLock object 2327db96d56Sopenharmony_ci is created and used as the underlying lock. 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci """ 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci def __init__(self, lock=None): 2377db96d56Sopenharmony_ci if lock is None: 2387db96d56Sopenharmony_ci lock = RLock() 2397db96d56Sopenharmony_ci self._lock = lock 2407db96d56Sopenharmony_ci # Export the lock's acquire() and release() methods 2417db96d56Sopenharmony_ci self.acquire = lock.acquire 2427db96d56Sopenharmony_ci self.release = lock.release 2437db96d56Sopenharmony_ci # If the lock defines _release_save() and/or _acquire_restore(), 2447db96d56Sopenharmony_ci # these override the default implementations (which just call 2457db96d56Sopenharmony_ci # release() and acquire() on the lock). Ditto for _is_owned(). 2467db96d56Sopenharmony_ci try: 2477db96d56Sopenharmony_ci self._release_save = lock._release_save 2487db96d56Sopenharmony_ci except AttributeError: 2497db96d56Sopenharmony_ci pass 2507db96d56Sopenharmony_ci try: 2517db96d56Sopenharmony_ci self._acquire_restore = lock._acquire_restore 2527db96d56Sopenharmony_ci except AttributeError: 2537db96d56Sopenharmony_ci pass 2547db96d56Sopenharmony_ci try: 2557db96d56Sopenharmony_ci self._is_owned = lock._is_owned 2567db96d56Sopenharmony_ci except AttributeError: 2577db96d56Sopenharmony_ci pass 2587db96d56Sopenharmony_ci self._waiters = _deque() 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci def _at_fork_reinit(self): 2617db96d56Sopenharmony_ci self._lock._at_fork_reinit() 2627db96d56Sopenharmony_ci self._waiters.clear() 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_ci def __enter__(self): 2657db96d56Sopenharmony_ci return self._lock.__enter__() 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci def __exit__(self, *args): 2687db96d56Sopenharmony_ci return self._lock.__exit__(*args) 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci def __repr__(self): 2717db96d56Sopenharmony_ci return "<Condition(%s, %d)>" % (self._lock, len(self._waiters)) 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci def _release_save(self): 2747db96d56Sopenharmony_ci self._lock.release() # No state to save 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci def _acquire_restore(self, x): 2777db96d56Sopenharmony_ci self._lock.acquire() # Ignore saved state 2787db96d56Sopenharmony_ci 2797db96d56Sopenharmony_ci def _is_owned(self): 2807db96d56Sopenharmony_ci # Return True if lock is owned by current_thread. 2817db96d56Sopenharmony_ci # This method is called only if _lock doesn't have _is_owned(). 2827db96d56Sopenharmony_ci if self._lock.acquire(False): 2837db96d56Sopenharmony_ci self._lock.release() 2847db96d56Sopenharmony_ci return False 2857db96d56Sopenharmony_ci else: 2867db96d56Sopenharmony_ci return True 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci def wait(self, timeout=None): 2897db96d56Sopenharmony_ci """Wait until notified or until a timeout occurs. 2907db96d56Sopenharmony_ci 2917db96d56Sopenharmony_ci If the calling thread has not acquired the lock when this method is 2927db96d56Sopenharmony_ci called, a RuntimeError is raised. 2937db96d56Sopenharmony_ci 2947db96d56Sopenharmony_ci This method releases the underlying lock, and then blocks until it is 2957db96d56Sopenharmony_ci awakened by a notify() or notify_all() call for the same condition 2967db96d56Sopenharmony_ci variable in another thread, or until the optional timeout occurs. Once 2977db96d56Sopenharmony_ci awakened or timed out, it re-acquires the lock and returns. 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci When the timeout argument is present and not None, it should be a 3007db96d56Sopenharmony_ci floating point number specifying a timeout for the operation in seconds 3017db96d56Sopenharmony_ci (or fractions thereof). 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci When the underlying lock is an RLock, it is not released using its 3047db96d56Sopenharmony_ci release() method, since this may not actually unlock the lock when it 3057db96d56Sopenharmony_ci was acquired multiple times recursively. Instead, an internal interface 3067db96d56Sopenharmony_ci of the RLock class is used, which really unlocks it even when it has 3077db96d56Sopenharmony_ci been recursively acquired several times. Another internal interface is 3087db96d56Sopenharmony_ci then used to restore the recursion level when the lock is reacquired. 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_ci """ 3117db96d56Sopenharmony_ci if not self._is_owned(): 3127db96d56Sopenharmony_ci raise RuntimeError("cannot wait on un-acquired lock") 3137db96d56Sopenharmony_ci waiter = _allocate_lock() 3147db96d56Sopenharmony_ci waiter.acquire() 3157db96d56Sopenharmony_ci self._waiters.append(waiter) 3167db96d56Sopenharmony_ci saved_state = self._release_save() 3177db96d56Sopenharmony_ci gotit = False 3187db96d56Sopenharmony_ci try: # restore state no matter what (e.g., KeyboardInterrupt) 3197db96d56Sopenharmony_ci if timeout is None: 3207db96d56Sopenharmony_ci waiter.acquire() 3217db96d56Sopenharmony_ci gotit = True 3227db96d56Sopenharmony_ci else: 3237db96d56Sopenharmony_ci if timeout > 0: 3247db96d56Sopenharmony_ci gotit = waiter.acquire(True, timeout) 3257db96d56Sopenharmony_ci else: 3267db96d56Sopenharmony_ci gotit = waiter.acquire(False) 3277db96d56Sopenharmony_ci return gotit 3287db96d56Sopenharmony_ci finally: 3297db96d56Sopenharmony_ci self._acquire_restore(saved_state) 3307db96d56Sopenharmony_ci if not gotit: 3317db96d56Sopenharmony_ci try: 3327db96d56Sopenharmony_ci self._waiters.remove(waiter) 3337db96d56Sopenharmony_ci except ValueError: 3347db96d56Sopenharmony_ci pass 3357db96d56Sopenharmony_ci 3367db96d56Sopenharmony_ci def wait_for(self, predicate, timeout=None): 3377db96d56Sopenharmony_ci """Wait until a condition evaluates to True. 3387db96d56Sopenharmony_ci 3397db96d56Sopenharmony_ci predicate should be a callable which result will be interpreted as a 3407db96d56Sopenharmony_ci boolean value. A timeout may be provided giving the maximum time to 3417db96d56Sopenharmony_ci wait. 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_ci """ 3447db96d56Sopenharmony_ci endtime = None 3457db96d56Sopenharmony_ci waittime = timeout 3467db96d56Sopenharmony_ci result = predicate() 3477db96d56Sopenharmony_ci while not result: 3487db96d56Sopenharmony_ci if waittime is not None: 3497db96d56Sopenharmony_ci if endtime is None: 3507db96d56Sopenharmony_ci endtime = _time() + waittime 3517db96d56Sopenharmony_ci else: 3527db96d56Sopenharmony_ci waittime = endtime - _time() 3537db96d56Sopenharmony_ci if waittime <= 0: 3547db96d56Sopenharmony_ci break 3557db96d56Sopenharmony_ci self.wait(waittime) 3567db96d56Sopenharmony_ci result = predicate() 3577db96d56Sopenharmony_ci return result 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci def notify(self, n=1): 3607db96d56Sopenharmony_ci """Wake up one or more threads waiting on this condition, if any. 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci If the calling thread has not acquired the lock when this method is 3637db96d56Sopenharmony_ci called, a RuntimeError is raised. 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_ci This method wakes up at most n of the threads waiting for the condition 3667db96d56Sopenharmony_ci variable; it is a no-op if no threads are waiting. 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci """ 3697db96d56Sopenharmony_ci if not self._is_owned(): 3707db96d56Sopenharmony_ci raise RuntimeError("cannot notify on un-acquired lock") 3717db96d56Sopenharmony_ci waiters = self._waiters 3727db96d56Sopenharmony_ci while waiters and n > 0: 3737db96d56Sopenharmony_ci waiter = waiters[0] 3747db96d56Sopenharmony_ci try: 3757db96d56Sopenharmony_ci waiter.release() 3767db96d56Sopenharmony_ci except RuntimeError: 3777db96d56Sopenharmony_ci # gh-92530: The previous call of notify() released the lock, 3787db96d56Sopenharmony_ci # but was interrupted before removing it from the queue. 3797db96d56Sopenharmony_ci # It can happen if a signal handler raises an exception, 3807db96d56Sopenharmony_ci # like CTRL+C which raises KeyboardInterrupt. 3817db96d56Sopenharmony_ci pass 3827db96d56Sopenharmony_ci else: 3837db96d56Sopenharmony_ci n -= 1 3847db96d56Sopenharmony_ci try: 3857db96d56Sopenharmony_ci waiters.remove(waiter) 3867db96d56Sopenharmony_ci except ValueError: 3877db96d56Sopenharmony_ci pass 3887db96d56Sopenharmony_ci 3897db96d56Sopenharmony_ci def notify_all(self): 3907db96d56Sopenharmony_ci """Wake up all threads waiting on this condition. 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci If the calling thread has not acquired the lock when this method 3937db96d56Sopenharmony_ci is called, a RuntimeError is raised. 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_ci """ 3967db96d56Sopenharmony_ci self.notify(len(self._waiters)) 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci def notifyAll(self): 3997db96d56Sopenharmony_ci """Wake up all threads waiting on this condition. 4007db96d56Sopenharmony_ci 4017db96d56Sopenharmony_ci This method is deprecated, use notify_all() instead. 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci """ 4047db96d56Sopenharmony_ci import warnings 4057db96d56Sopenharmony_ci warnings.warn('notifyAll() is deprecated, use notify_all() instead', 4067db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 4077db96d56Sopenharmony_ci self.notify_all() 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci 4107db96d56Sopenharmony_ciclass Semaphore: 4117db96d56Sopenharmony_ci """This class implements semaphore objects. 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ci Semaphores manage a counter representing the number of release() calls minus 4147db96d56Sopenharmony_ci the number of acquire() calls, plus an initial value. The acquire() method 4157db96d56Sopenharmony_ci blocks if necessary until it can return without making the counter 4167db96d56Sopenharmony_ci negative. If not given, value defaults to 1. 4177db96d56Sopenharmony_ci 4187db96d56Sopenharmony_ci """ 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci # After Tim Peters' semaphore class, but not quite the same (no maximum) 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci def __init__(self, value=1): 4237db96d56Sopenharmony_ci if value < 0: 4247db96d56Sopenharmony_ci raise ValueError("semaphore initial value must be >= 0") 4257db96d56Sopenharmony_ci self._cond = Condition(Lock()) 4267db96d56Sopenharmony_ci self._value = value 4277db96d56Sopenharmony_ci 4287db96d56Sopenharmony_ci def __repr__(self): 4297db96d56Sopenharmony_ci cls = self.__class__ 4307db96d56Sopenharmony_ci return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:" 4317db96d56Sopenharmony_ci f" value={self._value}>") 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_ci def acquire(self, blocking=True, timeout=None): 4347db96d56Sopenharmony_ci """Acquire a semaphore, decrementing the internal counter by one. 4357db96d56Sopenharmony_ci 4367db96d56Sopenharmony_ci When invoked without arguments: if the internal counter is larger than 4377db96d56Sopenharmony_ci zero on entry, decrement it by one and return immediately. If it is zero 4387db96d56Sopenharmony_ci on entry, block, waiting until some other thread has called release() to 4397db96d56Sopenharmony_ci make it larger than zero. This is done with proper interlocking so that 4407db96d56Sopenharmony_ci if multiple acquire() calls are blocked, release() will wake exactly one 4417db96d56Sopenharmony_ci of them up. The implementation may pick one at random, so the order in 4427db96d56Sopenharmony_ci which blocked threads are awakened should not be relied on. There is no 4437db96d56Sopenharmony_ci return value in this case. 4447db96d56Sopenharmony_ci 4457db96d56Sopenharmony_ci When invoked with blocking set to true, do the same thing as when called 4467db96d56Sopenharmony_ci without arguments, and return true. 4477db96d56Sopenharmony_ci 4487db96d56Sopenharmony_ci When invoked with blocking set to false, do not block. If a call without 4497db96d56Sopenharmony_ci an argument would block, return false immediately; otherwise, do the 4507db96d56Sopenharmony_ci same thing as when called without arguments, and return true. 4517db96d56Sopenharmony_ci 4527db96d56Sopenharmony_ci When invoked with a timeout other than None, it will block for at 4537db96d56Sopenharmony_ci most timeout seconds. If acquire does not complete successfully in 4547db96d56Sopenharmony_ci that interval, return false. Return true otherwise. 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci """ 4577db96d56Sopenharmony_ci if not blocking and timeout is not None: 4587db96d56Sopenharmony_ci raise ValueError("can't specify timeout for non-blocking acquire") 4597db96d56Sopenharmony_ci rc = False 4607db96d56Sopenharmony_ci endtime = None 4617db96d56Sopenharmony_ci with self._cond: 4627db96d56Sopenharmony_ci while self._value == 0: 4637db96d56Sopenharmony_ci if not blocking: 4647db96d56Sopenharmony_ci break 4657db96d56Sopenharmony_ci if timeout is not None: 4667db96d56Sopenharmony_ci if endtime is None: 4677db96d56Sopenharmony_ci endtime = _time() + timeout 4687db96d56Sopenharmony_ci else: 4697db96d56Sopenharmony_ci timeout = endtime - _time() 4707db96d56Sopenharmony_ci if timeout <= 0: 4717db96d56Sopenharmony_ci break 4727db96d56Sopenharmony_ci self._cond.wait(timeout) 4737db96d56Sopenharmony_ci else: 4747db96d56Sopenharmony_ci self._value -= 1 4757db96d56Sopenharmony_ci rc = True 4767db96d56Sopenharmony_ci return rc 4777db96d56Sopenharmony_ci 4787db96d56Sopenharmony_ci __enter__ = acquire 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci def release(self, n=1): 4817db96d56Sopenharmony_ci """Release a semaphore, incrementing the internal counter by one or more. 4827db96d56Sopenharmony_ci 4837db96d56Sopenharmony_ci When the counter is zero on entry and another thread is waiting for it 4847db96d56Sopenharmony_ci to become larger than zero again, wake up that thread. 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ci """ 4877db96d56Sopenharmony_ci if n < 1: 4887db96d56Sopenharmony_ci raise ValueError('n must be one or more') 4897db96d56Sopenharmony_ci with self._cond: 4907db96d56Sopenharmony_ci self._value += n 4917db96d56Sopenharmony_ci for i in range(n): 4927db96d56Sopenharmony_ci self._cond.notify() 4937db96d56Sopenharmony_ci 4947db96d56Sopenharmony_ci def __exit__(self, t, v, tb): 4957db96d56Sopenharmony_ci self.release() 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci 4987db96d56Sopenharmony_ciclass BoundedSemaphore(Semaphore): 4997db96d56Sopenharmony_ci """Implements a bounded semaphore. 5007db96d56Sopenharmony_ci 5017db96d56Sopenharmony_ci A bounded semaphore checks to make sure its current value doesn't exceed its 5027db96d56Sopenharmony_ci initial value. If it does, ValueError is raised. In most situations 5037db96d56Sopenharmony_ci semaphores are used to guard resources with limited capacity. 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ci If the semaphore is released too many times it's a sign of a bug. If not 5067db96d56Sopenharmony_ci given, value defaults to 1. 5077db96d56Sopenharmony_ci 5087db96d56Sopenharmony_ci Like regular semaphores, bounded semaphores manage a counter representing 5097db96d56Sopenharmony_ci the number of release() calls minus the number of acquire() calls, plus an 5107db96d56Sopenharmony_ci initial value. The acquire() method blocks if necessary until it can return 5117db96d56Sopenharmony_ci without making the counter negative. If not given, value defaults to 1. 5127db96d56Sopenharmony_ci 5137db96d56Sopenharmony_ci """ 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci def __init__(self, value=1): 5167db96d56Sopenharmony_ci Semaphore.__init__(self, value) 5177db96d56Sopenharmony_ci self._initial_value = value 5187db96d56Sopenharmony_ci 5197db96d56Sopenharmony_ci def __repr__(self): 5207db96d56Sopenharmony_ci cls = self.__class__ 5217db96d56Sopenharmony_ci return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:" 5227db96d56Sopenharmony_ci f" value={self._value}/{self._initial_value}>") 5237db96d56Sopenharmony_ci 5247db96d56Sopenharmony_ci def release(self, n=1): 5257db96d56Sopenharmony_ci """Release a semaphore, incrementing the internal counter by one or more. 5267db96d56Sopenharmony_ci 5277db96d56Sopenharmony_ci When the counter is zero on entry and another thread is waiting for it 5287db96d56Sopenharmony_ci to become larger than zero again, wake up that thread. 5297db96d56Sopenharmony_ci 5307db96d56Sopenharmony_ci If the number of releases exceeds the number of acquires, 5317db96d56Sopenharmony_ci raise a ValueError. 5327db96d56Sopenharmony_ci 5337db96d56Sopenharmony_ci """ 5347db96d56Sopenharmony_ci if n < 1: 5357db96d56Sopenharmony_ci raise ValueError('n must be one or more') 5367db96d56Sopenharmony_ci with self._cond: 5377db96d56Sopenharmony_ci if self._value + n > self._initial_value: 5387db96d56Sopenharmony_ci raise ValueError("Semaphore released too many times") 5397db96d56Sopenharmony_ci self._value += n 5407db96d56Sopenharmony_ci for i in range(n): 5417db96d56Sopenharmony_ci self._cond.notify() 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci 5447db96d56Sopenharmony_ciclass Event: 5457db96d56Sopenharmony_ci """Class implementing event objects. 5467db96d56Sopenharmony_ci 5477db96d56Sopenharmony_ci Events manage a flag that can be set to true with the set() method and reset 5487db96d56Sopenharmony_ci to false with the clear() method. The wait() method blocks until the flag is 5497db96d56Sopenharmony_ci true. The flag is initially false. 5507db96d56Sopenharmony_ci 5517db96d56Sopenharmony_ci """ 5527db96d56Sopenharmony_ci 5537db96d56Sopenharmony_ci # After Tim Peters' event class (without is_posted()) 5547db96d56Sopenharmony_ci 5557db96d56Sopenharmony_ci def __init__(self): 5567db96d56Sopenharmony_ci self._cond = Condition(Lock()) 5577db96d56Sopenharmony_ci self._flag = False 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_ci def __repr__(self): 5607db96d56Sopenharmony_ci cls = self.__class__ 5617db96d56Sopenharmony_ci status = 'set' if self._flag else 'unset' 5627db96d56Sopenharmony_ci return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: {status}>" 5637db96d56Sopenharmony_ci 5647db96d56Sopenharmony_ci def _at_fork_reinit(self): 5657db96d56Sopenharmony_ci # Private method called by Thread._reset_internal_locks() 5667db96d56Sopenharmony_ci self._cond._at_fork_reinit() 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_ci def is_set(self): 5697db96d56Sopenharmony_ci """Return true if and only if the internal flag is true.""" 5707db96d56Sopenharmony_ci return self._flag 5717db96d56Sopenharmony_ci 5727db96d56Sopenharmony_ci def isSet(self): 5737db96d56Sopenharmony_ci """Return true if and only if the internal flag is true. 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_ci This method is deprecated, use is_set() instead. 5767db96d56Sopenharmony_ci 5777db96d56Sopenharmony_ci """ 5787db96d56Sopenharmony_ci import warnings 5797db96d56Sopenharmony_ci warnings.warn('isSet() is deprecated, use is_set() instead', 5807db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 5817db96d56Sopenharmony_ci return self.is_set() 5827db96d56Sopenharmony_ci 5837db96d56Sopenharmony_ci def set(self): 5847db96d56Sopenharmony_ci """Set the internal flag to true. 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ci All threads waiting for it to become true are awakened. Threads 5877db96d56Sopenharmony_ci that call wait() once the flag is true will not block at all. 5887db96d56Sopenharmony_ci 5897db96d56Sopenharmony_ci """ 5907db96d56Sopenharmony_ci with self._cond: 5917db96d56Sopenharmony_ci self._flag = True 5927db96d56Sopenharmony_ci self._cond.notify_all() 5937db96d56Sopenharmony_ci 5947db96d56Sopenharmony_ci def clear(self): 5957db96d56Sopenharmony_ci """Reset the internal flag to false. 5967db96d56Sopenharmony_ci 5977db96d56Sopenharmony_ci Subsequently, threads calling wait() will block until set() is called to 5987db96d56Sopenharmony_ci set the internal flag to true again. 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_ci """ 6017db96d56Sopenharmony_ci with self._cond: 6027db96d56Sopenharmony_ci self._flag = False 6037db96d56Sopenharmony_ci 6047db96d56Sopenharmony_ci def wait(self, timeout=None): 6057db96d56Sopenharmony_ci """Block until the internal flag is true. 6067db96d56Sopenharmony_ci 6077db96d56Sopenharmony_ci If the internal flag is true on entry, return immediately. Otherwise, 6087db96d56Sopenharmony_ci block until another thread calls set() to set the flag to true, or until 6097db96d56Sopenharmony_ci the optional timeout occurs. 6107db96d56Sopenharmony_ci 6117db96d56Sopenharmony_ci When the timeout argument is present and not None, it should be a 6127db96d56Sopenharmony_ci floating point number specifying a timeout for the operation in seconds 6137db96d56Sopenharmony_ci (or fractions thereof). 6147db96d56Sopenharmony_ci 6157db96d56Sopenharmony_ci This method returns the internal flag on exit, so it will always return 6167db96d56Sopenharmony_ci True except if a timeout is given and the operation times out. 6177db96d56Sopenharmony_ci 6187db96d56Sopenharmony_ci """ 6197db96d56Sopenharmony_ci with self._cond: 6207db96d56Sopenharmony_ci signaled = self._flag 6217db96d56Sopenharmony_ci if not signaled: 6227db96d56Sopenharmony_ci signaled = self._cond.wait(timeout) 6237db96d56Sopenharmony_ci return signaled 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ci 6267db96d56Sopenharmony_ci# A barrier class. Inspired in part by the pthread_barrier_* api and 6277db96d56Sopenharmony_ci# the CyclicBarrier class from Java. See 6287db96d56Sopenharmony_ci# http://sourceware.org/pthreads-win32/manual/pthread_barrier_init.html and 6297db96d56Sopenharmony_ci# http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ 6307db96d56Sopenharmony_ci# CyclicBarrier.html 6317db96d56Sopenharmony_ci# for information. 6327db96d56Sopenharmony_ci# We maintain two main states, 'filling' and 'draining' enabling the barrier 6337db96d56Sopenharmony_ci# to be cyclic. Threads are not allowed into it until it has fully drained 6347db96d56Sopenharmony_ci# since the previous cycle. In addition, a 'resetting' state exists which is 6357db96d56Sopenharmony_ci# similar to 'draining' except that threads leave with a BrokenBarrierError, 6367db96d56Sopenharmony_ci# and a 'broken' state in which all threads get the exception. 6377db96d56Sopenharmony_ciclass Barrier: 6387db96d56Sopenharmony_ci """Implements a Barrier. 6397db96d56Sopenharmony_ci 6407db96d56Sopenharmony_ci Useful for synchronizing a fixed number of threads at known synchronization 6417db96d56Sopenharmony_ci points. Threads block on 'wait()' and are simultaneously awoken once they 6427db96d56Sopenharmony_ci have all made that call. 6437db96d56Sopenharmony_ci 6447db96d56Sopenharmony_ci """ 6457db96d56Sopenharmony_ci 6467db96d56Sopenharmony_ci def __init__(self, parties, action=None, timeout=None): 6477db96d56Sopenharmony_ci """Create a barrier, initialised to 'parties' threads. 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci 'action' is a callable which, when supplied, will be called by one of 6507db96d56Sopenharmony_ci the threads after they have all entered the barrier and just prior to 6517db96d56Sopenharmony_ci releasing them all. If a 'timeout' is provided, it is used as the 6527db96d56Sopenharmony_ci default for all subsequent 'wait()' calls. 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci """ 6557db96d56Sopenharmony_ci self._cond = Condition(Lock()) 6567db96d56Sopenharmony_ci self._action = action 6577db96d56Sopenharmony_ci self._timeout = timeout 6587db96d56Sopenharmony_ci self._parties = parties 6597db96d56Sopenharmony_ci self._state = 0 # 0 filling, 1 draining, -1 resetting, -2 broken 6607db96d56Sopenharmony_ci self._count = 0 6617db96d56Sopenharmony_ci 6627db96d56Sopenharmony_ci def __repr__(self): 6637db96d56Sopenharmony_ci cls = self.__class__ 6647db96d56Sopenharmony_ci if self.broken: 6657db96d56Sopenharmony_ci return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: broken>" 6667db96d56Sopenharmony_ci return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:" 6677db96d56Sopenharmony_ci f" waiters={self.n_waiting}/{self.parties}>") 6687db96d56Sopenharmony_ci 6697db96d56Sopenharmony_ci def wait(self, timeout=None): 6707db96d56Sopenharmony_ci """Wait for the barrier. 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci When the specified number of threads have started waiting, they are all 6737db96d56Sopenharmony_ci simultaneously awoken. If an 'action' was provided for the barrier, one 6747db96d56Sopenharmony_ci of the threads will have executed that callback prior to returning. 6757db96d56Sopenharmony_ci Returns an individual index number from 0 to 'parties-1'. 6767db96d56Sopenharmony_ci 6777db96d56Sopenharmony_ci """ 6787db96d56Sopenharmony_ci if timeout is None: 6797db96d56Sopenharmony_ci timeout = self._timeout 6807db96d56Sopenharmony_ci with self._cond: 6817db96d56Sopenharmony_ci self._enter() # Block while the barrier drains. 6827db96d56Sopenharmony_ci index = self._count 6837db96d56Sopenharmony_ci self._count += 1 6847db96d56Sopenharmony_ci try: 6857db96d56Sopenharmony_ci if index + 1 == self._parties: 6867db96d56Sopenharmony_ci # We release the barrier 6877db96d56Sopenharmony_ci self._release() 6887db96d56Sopenharmony_ci else: 6897db96d56Sopenharmony_ci # We wait until someone releases us 6907db96d56Sopenharmony_ci self._wait(timeout) 6917db96d56Sopenharmony_ci return index 6927db96d56Sopenharmony_ci finally: 6937db96d56Sopenharmony_ci self._count -= 1 6947db96d56Sopenharmony_ci # Wake up any threads waiting for barrier to drain. 6957db96d56Sopenharmony_ci self._exit() 6967db96d56Sopenharmony_ci 6977db96d56Sopenharmony_ci # Block until the barrier is ready for us, or raise an exception 6987db96d56Sopenharmony_ci # if it is broken. 6997db96d56Sopenharmony_ci def _enter(self): 7007db96d56Sopenharmony_ci while self._state in (-1, 1): 7017db96d56Sopenharmony_ci # It is draining or resetting, wait until done 7027db96d56Sopenharmony_ci self._cond.wait() 7037db96d56Sopenharmony_ci #see if the barrier is in a broken state 7047db96d56Sopenharmony_ci if self._state < 0: 7057db96d56Sopenharmony_ci raise BrokenBarrierError 7067db96d56Sopenharmony_ci assert self._state == 0 7077db96d56Sopenharmony_ci 7087db96d56Sopenharmony_ci # Optionally run the 'action' and release the threads waiting 7097db96d56Sopenharmony_ci # in the barrier. 7107db96d56Sopenharmony_ci def _release(self): 7117db96d56Sopenharmony_ci try: 7127db96d56Sopenharmony_ci if self._action: 7137db96d56Sopenharmony_ci self._action() 7147db96d56Sopenharmony_ci # enter draining state 7157db96d56Sopenharmony_ci self._state = 1 7167db96d56Sopenharmony_ci self._cond.notify_all() 7177db96d56Sopenharmony_ci except: 7187db96d56Sopenharmony_ci #an exception during the _action handler. Break and reraise 7197db96d56Sopenharmony_ci self._break() 7207db96d56Sopenharmony_ci raise 7217db96d56Sopenharmony_ci 7227db96d56Sopenharmony_ci # Wait in the barrier until we are released. Raise an exception 7237db96d56Sopenharmony_ci # if the barrier is reset or broken. 7247db96d56Sopenharmony_ci def _wait(self, timeout): 7257db96d56Sopenharmony_ci if not self._cond.wait_for(lambda : self._state != 0, timeout): 7267db96d56Sopenharmony_ci #timed out. Break the barrier 7277db96d56Sopenharmony_ci self._break() 7287db96d56Sopenharmony_ci raise BrokenBarrierError 7297db96d56Sopenharmony_ci if self._state < 0: 7307db96d56Sopenharmony_ci raise BrokenBarrierError 7317db96d56Sopenharmony_ci assert self._state == 1 7327db96d56Sopenharmony_ci 7337db96d56Sopenharmony_ci # If we are the last thread to exit the barrier, signal any threads 7347db96d56Sopenharmony_ci # waiting for the barrier to drain. 7357db96d56Sopenharmony_ci def _exit(self): 7367db96d56Sopenharmony_ci if self._count == 0: 7377db96d56Sopenharmony_ci if self._state in (-1, 1): 7387db96d56Sopenharmony_ci #resetting or draining 7397db96d56Sopenharmony_ci self._state = 0 7407db96d56Sopenharmony_ci self._cond.notify_all() 7417db96d56Sopenharmony_ci 7427db96d56Sopenharmony_ci def reset(self): 7437db96d56Sopenharmony_ci """Reset the barrier to the initial state. 7447db96d56Sopenharmony_ci 7457db96d56Sopenharmony_ci Any threads currently waiting will get the BrokenBarrier exception 7467db96d56Sopenharmony_ci raised. 7477db96d56Sopenharmony_ci 7487db96d56Sopenharmony_ci """ 7497db96d56Sopenharmony_ci with self._cond: 7507db96d56Sopenharmony_ci if self._count > 0: 7517db96d56Sopenharmony_ci if self._state == 0: 7527db96d56Sopenharmony_ci #reset the barrier, waking up threads 7537db96d56Sopenharmony_ci self._state = -1 7547db96d56Sopenharmony_ci elif self._state == -2: 7557db96d56Sopenharmony_ci #was broken, set it to reset state 7567db96d56Sopenharmony_ci #which clears when the last thread exits 7577db96d56Sopenharmony_ci self._state = -1 7587db96d56Sopenharmony_ci else: 7597db96d56Sopenharmony_ci self._state = 0 7607db96d56Sopenharmony_ci self._cond.notify_all() 7617db96d56Sopenharmony_ci 7627db96d56Sopenharmony_ci def abort(self): 7637db96d56Sopenharmony_ci """Place the barrier into a 'broken' state. 7647db96d56Sopenharmony_ci 7657db96d56Sopenharmony_ci Useful in case of error. Any currently waiting threads and threads 7667db96d56Sopenharmony_ci attempting to 'wait()' will have BrokenBarrierError raised. 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_ci """ 7697db96d56Sopenharmony_ci with self._cond: 7707db96d56Sopenharmony_ci self._break() 7717db96d56Sopenharmony_ci 7727db96d56Sopenharmony_ci def _break(self): 7737db96d56Sopenharmony_ci # An internal error was detected. The barrier is set to 7747db96d56Sopenharmony_ci # a broken state all parties awakened. 7757db96d56Sopenharmony_ci self._state = -2 7767db96d56Sopenharmony_ci self._cond.notify_all() 7777db96d56Sopenharmony_ci 7787db96d56Sopenharmony_ci @property 7797db96d56Sopenharmony_ci def parties(self): 7807db96d56Sopenharmony_ci """Return the number of threads required to trip the barrier.""" 7817db96d56Sopenharmony_ci return self._parties 7827db96d56Sopenharmony_ci 7837db96d56Sopenharmony_ci @property 7847db96d56Sopenharmony_ci def n_waiting(self): 7857db96d56Sopenharmony_ci """Return the number of threads currently waiting at the barrier.""" 7867db96d56Sopenharmony_ci # We don't need synchronization here since this is an ephemeral result 7877db96d56Sopenharmony_ci # anyway. It returns the correct value in the steady state. 7887db96d56Sopenharmony_ci if self._state == 0: 7897db96d56Sopenharmony_ci return self._count 7907db96d56Sopenharmony_ci return 0 7917db96d56Sopenharmony_ci 7927db96d56Sopenharmony_ci @property 7937db96d56Sopenharmony_ci def broken(self): 7947db96d56Sopenharmony_ci """Return True if the barrier is in a broken state.""" 7957db96d56Sopenharmony_ci return self._state == -2 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci# exception raised by the Barrier class 7987db96d56Sopenharmony_ciclass BrokenBarrierError(RuntimeError): 7997db96d56Sopenharmony_ci pass 8007db96d56Sopenharmony_ci 8017db96d56Sopenharmony_ci 8027db96d56Sopenharmony_ci# Helper to generate new thread names 8037db96d56Sopenharmony_ci_counter = _count(1).__next__ 8047db96d56Sopenharmony_cidef _newname(name_template): 8057db96d56Sopenharmony_ci return name_template % _counter() 8067db96d56Sopenharmony_ci 8077db96d56Sopenharmony_ci# Active thread administration. 8087db96d56Sopenharmony_ci# 8097db96d56Sopenharmony_ci# bpo-44422: Use a reentrant lock to allow reentrant calls to functions like 8107db96d56Sopenharmony_ci# threading.enumerate(). 8117db96d56Sopenharmony_ci_active_limbo_lock = RLock() 8127db96d56Sopenharmony_ci_active = {} # maps thread id to Thread object 8137db96d56Sopenharmony_ci_limbo = {} 8147db96d56Sopenharmony_ci_dangling = WeakSet() 8157db96d56Sopenharmony_ci 8167db96d56Sopenharmony_ci# Set of Thread._tstate_lock locks of non-daemon threads used by _shutdown() 8177db96d56Sopenharmony_ci# to wait until all Python thread states get deleted: 8187db96d56Sopenharmony_ci# see Thread._set_tstate_lock(). 8197db96d56Sopenharmony_ci_shutdown_locks_lock = _allocate_lock() 8207db96d56Sopenharmony_ci_shutdown_locks = set() 8217db96d56Sopenharmony_ci 8227db96d56Sopenharmony_cidef _maintain_shutdown_locks(): 8237db96d56Sopenharmony_ci """ 8247db96d56Sopenharmony_ci Drop any shutdown locks that don't correspond to running threads anymore. 8257db96d56Sopenharmony_ci 8267db96d56Sopenharmony_ci Calling this from time to time avoids an ever-growing _shutdown_locks 8277db96d56Sopenharmony_ci set when Thread objects are not joined explicitly. See bpo-37788. 8287db96d56Sopenharmony_ci 8297db96d56Sopenharmony_ci This must be called with _shutdown_locks_lock acquired. 8307db96d56Sopenharmony_ci """ 8317db96d56Sopenharmony_ci # If a lock was released, the corresponding thread has exited 8327db96d56Sopenharmony_ci to_remove = [lock for lock in _shutdown_locks if not lock.locked()] 8337db96d56Sopenharmony_ci _shutdown_locks.difference_update(to_remove) 8347db96d56Sopenharmony_ci 8357db96d56Sopenharmony_ci 8367db96d56Sopenharmony_ci# Main class for threads 8377db96d56Sopenharmony_ci 8387db96d56Sopenharmony_ciclass Thread: 8397db96d56Sopenharmony_ci """A class that represents a thread of control. 8407db96d56Sopenharmony_ci 8417db96d56Sopenharmony_ci This class can be safely subclassed in a limited fashion. There are two ways 8427db96d56Sopenharmony_ci to specify the activity: by passing a callable object to the constructor, or 8437db96d56Sopenharmony_ci by overriding the run() method in a subclass. 8447db96d56Sopenharmony_ci 8457db96d56Sopenharmony_ci """ 8467db96d56Sopenharmony_ci 8477db96d56Sopenharmony_ci _initialized = False 8487db96d56Sopenharmony_ci 8497db96d56Sopenharmony_ci def __init__(self, group=None, target=None, name=None, 8507db96d56Sopenharmony_ci args=(), kwargs=None, *, daemon=None): 8517db96d56Sopenharmony_ci """This constructor should always be called with keyword arguments. Arguments are: 8527db96d56Sopenharmony_ci 8537db96d56Sopenharmony_ci *group* should be None; reserved for future extension when a ThreadGroup 8547db96d56Sopenharmony_ci class is implemented. 8557db96d56Sopenharmony_ci 8567db96d56Sopenharmony_ci *target* is the callable object to be invoked by the run() 8577db96d56Sopenharmony_ci method. Defaults to None, meaning nothing is called. 8587db96d56Sopenharmony_ci 8597db96d56Sopenharmony_ci *name* is the thread name. By default, a unique name is constructed of 8607db96d56Sopenharmony_ci the form "Thread-N" where N is a small decimal number. 8617db96d56Sopenharmony_ci 8627db96d56Sopenharmony_ci *args* is a list or tuple of arguments for the target invocation. Defaults to (). 8637db96d56Sopenharmony_ci 8647db96d56Sopenharmony_ci *kwargs* is a dictionary of keyword arguments for the target 8657db96d56Sopenharmony_ci invocation. Defaults to {}. 8667db96d56Sopenharmony_ci 8677db96d56Sopenharmony_ci If a subclass overrides the constructor, it must make sure to invoke 8687db96d56Sopenharmony_ci the base class constructor (Thread.__init__()) before doing anything 8697db96d56Sopenharmony_ci else to the thread. 8707db96d56Sopenharmony_ci 8717db96d56Sopenharmony_ci """ 8727db96d56Sopenharmony_ci assert group is None, "group argument must be None for now" 8737db96d56Sopenharmony_ci if kwargs is None: 8747db96d56Sopenharmony_ci kwargs = {} 8757db96d56Sopenharmony_ci if name: 8767db96d56Sopenharmony_ci name = str(name) 8777db96d56Sopenharmony_ci else: 8787db96d56Sopenharmony_ci name = _newname("Thread-%d") 8797db96d56Sopenharmony_ci if target is not None: 8807db96d56Sopenharmony_ci try: 8817db96d56Sopenharmony_ci target_name = target.__name__ 8827db96d56Sopenharmony_ci name += f" ({target_name})" 8837db96d56Sopenharmony_ci except AttributeError: 8847db96d56Sopenharmony_ci pass 8857db96d56Sopenharmony_ci 8867db96d56Sopenharmony_ci self._target = target 8877db96d56Sopenharmony_ci self._name = name 8887db96d56Sopenharmony_ci self._args = args 8897db96d56Sopenharmony_ci self._kwargs = kwargs 8907db96d56Sopenharmony_ci if daemon is not None: 8917db96d56Sopenharmony_ci self._daemonic = daemon 8927db96d56Sopenharmony_ci else: 8937db96d56Sopenharmony_ci self._daemonic = current_thread().daemon 8947db96d56Sopenharmony_ci self._ident = None 8957db96d56Sopenharmony_ci if _HAVE_THREAD_NATIVE_ID: 8967db96d56Sopenharmony_ci self._native_id = None 8977db96d56Sopenharmony_ci self._tstate_lock = None 8987db96d56Sopenharmony_ci self._started = Event() 8997db96d56Sopenharmony_ci self._is_stopped = False 9007db96d56Sopenharmony_ci self._initialized = True 9017db96d56Sopenharmony_ci # Copy of sys.stderr used by self._invoke_excepthook() 9027db96d56Sopenharmony_ci self._stderr = _sys.stderr 9037db96d56Sopenharmony_ci self._invoke_excepthook = _make_invoke_excepthook() 9047db96d56Sopenharmony_ci # For debugging and _after_fork() 9057db96d56Sopenharmony_ci _dangling.add(self) 9067db96d56Sopenharmony_ci 9077db96d56Sopenharmony_ci def _reset_internal_locks(self, is_alive): 9087db96d56Sopenharmony_ci # private! Called by _after_fork() to reset our internal locks as 9097db96d56Sopenharmony_ci # they may be in an invalid state leading to a deadlock or crash. 9107db96d56Sopenharmony_ci self._started._at_fork_reinit() 9117db96d56Sopenharmony_ci if is_alive: 9127db96d56Sopenharmony_ci # bpo-42350: If the fork happens when the thread is already stopped 9137db96d56Sopenharmony_ci # (ex: after threading._shutdown() has been called), _tstate_lock 9147db96d56Sopenharmony_ci # is None. Do nothing in this case. 9157db96d56Sopenharmony_ci if self._tstate_lock is not None: 9167db96d56Sopenharmony_ci self._tstate_lock._at_fork_reinit() 9177db96d56Sopenharmony_ci self._tstate_lock.acquire() 9187db96d56Sopenharmony_ci else: 9197db96d56Sopenharmony_ci # The thread isn't alive after fork: it doesn't have a tstate 9207db96d56Sopenharmony_ci # anymore. 9217db96d56Sopenharmony_ci self._is_stopped = True 9227db96d56Sopenharmony_ci self._tstate_lock = None 9237db96d56Sopenharmony_ci 9247db96d56Sopenharmony_ci def __repr__(self): 9257db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() was not called" 9267db96d56Sopenharmony_ci status = "initial" 9277db96d56Sopenharmony_ci if self._started.is_set(): 9287db96d56Sopenharmony_ci status = "started" 9297db96d56Sopenharmony_ci self.is_alive() # easy way to get ._is_stopped set when appropriate 9307db96d56Sopenharmony_ci if self._is_stopped: 9317db96d56Sopenharmony_ci status = "stopped" 9327db96d56Sopenharmony_ci if self._daemonic: 9337db96d56Sopenharmony_ci status += " daemon" 9347db96d56Sopenharmony_ci if self._ident is not None: 9357db96d56Sopenharmony_ci status += " %s" % self._ident 9367db96d56Sopenharmony_ci return "<%s(%s, %s)>" % (self.__class__.__name__, self._name, status) 9377db96d56Sopenharmony_ci 9387db96d56Sopenharmony_ci def start(self): 9397db96d56Sopenharmony_ci """Start the thread's activity. 9407db96d56Sopenharmony_ci 9417db96d56Sopenharmony_ci It must be called at most once per thread object. It arranges for the 9427db96d56Sopenharmony_ci object's run() method to be invoked in a separate thread of control. 9437db96d56Sopenharmony_ci 9447db96d56Sopenharmony_ci This method will raise a RuntimeError if called more than once on the 9457db96d56Sopenharmony_ci same thread object. 9467db96d56Sopenharmony_ci 9477db96d56Sopenharmony_ci """ 9487db96d56Sopenharmony_ci if not self._initialized: 9497db96d56Sopenharmony_ci raise RuntimeError("thread.__init__() not called") 9507db96d56Sopenharmony_ci 9517db96d56Sopenharmony_ci if self._started.is_set(): 9527db96d56Sopenharmony_ci raise RuntimeError("threads can only be started once") 9537db96d56Sopenharmony_ci 9547db96d56Sopenharmony_ci with _active_limbo_lock: 9557db96d56Sopenharmony_ci _limbo[self] = self 9567db96d56Sopenharmony_ci try: 9577db96d56Sopenharmony_ci _start_new_thread(self._bootstrap, ()) 9587db96d56Sopenharmony_ci except Exception: 9597db96d56Sopenharmony_ci with _active_limbo_lock: 9607db96d56Sopenharmony_ci del _limbo[self] 9617db96d56Sopenharmony_ci raise 9627db96d56Sopenharmony_ci self._started.wait() 9637db96d56Sopenharmony_ci 9647db96d56Sopenharmony_ci def run(self): 9657db96d56Sopenharmony_ci """Method representing the thread's activity. 9667db96d56Sopenharmony_ci 9677db96d56Sopenharmony_ci You may override this method in a subclass. The standard run() method 9687db96d56Sopenharmony_ci invokes the callable object passed to the object's constructor as the 9697db96d56Sopenharmony_ci target argument, if any, with sequential and keyword arguments taken 9707db96d56Sopenharmony_ci from the args and kwargs arguments, respectively. 9717db96d56Sopenharmony_ci 9727db96d56Sopenharmony_ci """ 9737db96d56Sopenharmony_ci try: 9747db96d56Sopenharmony_ci if self._target is not None: 9757db96d56Sopenharmony_ci self._target(*self._args, **self._kwargs) 9767db96d56Sopenharmony_ci finally: 9777db96d56Sopenharmony_ci # Avoid a refcycle if the thread is running a function with 9787db96d56Sopenharmony_ci # an argument that has a member that points to the thread. 9797db96d56Sopenharmony_ci del self._target, self._args, self._kwargs 9807db96d56Sopenharmony_ci 9817db96d56Sopenharmony_ci def _bootstrap(self): 9827db96d56Sopenharmony_ci # Wrapper around the real bootstrap code that ignores 9837db96d56Sopenharmony_ci # exceptions during interpreter cleanup. Those typically 9847db96d56Sopenharmony_ci # happen when a daemon thread wakes up at an unfortunate 9857db96d56Sopenharmony_ci # moment, finds the world around it destroyed, and raises some 9867db96d56Sopenharmony_ci # random exception *** while trying to report the exception in 9877db96d56Sopenharmony_ci # _bootstrap_inner() below ***. Those random exceptions 9887db96d56Sopenharmony_ci # don't help anybody, and they confuse users, so we suppress 9897db96d56Sopenharmony_ci # them. We suppress them only when it appears that the world 9907db96d56Sopenharmony_ci # indeed has already been destroyed, so that exceptions in 9917db96d56Sopenharmony_ci # _bootstrap_inner() during normal business hours are properly 9927db96d56Sopenharmony_ci # reported. Also, we only suppress them for daemonic threads; 9937db96d56Sopenharmony_ci # if a non-daemonic encounters this, something else is wrong. 9947db96d56Sopenharmony_ci try: 9957db96d56Sopenharmony_ci self._bootstrap_inner() 9967db96d56Sopenharmony_ci except: 9977db96d56Sopenharmony_ci if self._daemonic and _sys is None: 9987db96d56Sopenharmony_ci return 9997db96d56Sopenharmony_ci raise 10007db96d56Sopenharmony_ci 10017db96d56Sopenharmony_ci def _set_ident(self): 10027db96d56Sopenharmony_ci self._ident = get_ident() 10037db96d56Sopenharmony_ci 10047db96d56Sopenharmony_ci if _HAVE_THREAD_NATIVE_ID: 10057db96d56Sopenharmony_ci def _set_native_id(self): 10067db96d56Sopenharmony_ci self._native_id = get_native_id() 10077db96d56Sopenharmony_ci 10087db96d56Sopenharmony_ci def _set_tstate_lock(self): 10097db96d56Sopenharmony_ci """ 10107db96d56Sopenharmony_ci Set a lock object which will be released by the interpreter when 10117db96d56Sopenharmony_ci the underlying thread state (see pystate.h) gets deleted. 10127db96d56Sopenharmony_ci """ 10137db96d56Sopenharmony_ci self._tstate_lock = _set_sentinel() 10147db96d56Sopenharmony_ci self._tstate_lock.acquire() 10157db96d56Sopenharmony_ci 10167db96d56Sopenharmony_ci if not self.daemon: 10177db96d56Sopenharmony_ci with _shutdown_locks_lock: 10187db96d56Sopenharmony_ci _maintain_shutdown_locks() 10197db96d56Sopenharmony_ci _shutdown_locks.add(self._tstate_lock) 10207db96d56Sopenharmony_ci 10217db96d56Sopenharmony_ci def _bootstrap_inner(self): 10227db96d56Sopenharmony_ci try: 10237db96d56Sopenharmony_ci self._set_ident() 10247db96d56Sopenharmony_ci self._set_tstate_lock() 10257db96d56Sopenharmony_ci if _HAVE_THREAD_NATIVE_ID: 10267db96d56Sopenharmony_ci self._set_native_id() 10277db96d56Sopenharmony_ci self._started.set() 10287db96d56Sopenharmony_ci with _active_limbo_lock: 10297db96d56Sopenharmony_ci _active[self._ident] = self 10307db96d56Sopenharmony_ci del _limbo[self] 10317db96d56Sopenharmony_ci 10327db96d56Sopenharmony_ci if _trace_hook: 10337db96d56Sopenharmony_ci _sys.settrace(_trace_hook) 10347db96d56Sopenharmony_ci if _profile_hook: 10357db96d56Sopenharmony_ci _sys.setprofile(_profile_hook) 10367db96d56Sopenharmony_ci 10377db96d56Sopenharmony_ci try: 10387db96d56Sopenharmony_ci self.run() 10397db96d56Sopenharmony_ci except: 10407db96d56Sopenharmony_ci self._invoke_excepthook(self) 10417db96d56Sopenharmony_ci finally: 10427db96d56Sopenharmony_ci self._delete() 10437db96d56Sopenharmony_ci 10447db96d56Sopenharmony_ci def _stop(self): 10457db96d56Sopenharmony_ci # After calling ._stop(), .is_alive() returns False and .join() returns 10467db96d56Sopenharmony_ci # immediately. ._tstate_lock must be released before calling ._stop(). 10477db96d56Sopenharmony_ci # 10487db96d56Sopenharmony_ci # Normal case: C code at the end of the thread's life 10497db96d56Sopenharmony_ci # (release_sentinel in _threadmodule.c) releases ._tstate_lock, and 10507db96d56Sopenharmony_ci # that's detected by our ._wait_for_tstate_lock(), called by .join() 10517db96d56Sopenharmony_ci # and .is_alive(). Any number of threads _may_ call ._stop() 10527db96d56Sopenharmony_ci # simultaneously (for example, if multiple threads are blocked in 10537db96d56Sopenharmony_ci # .join() calls), and they're not serialized. That's harmless - 10547db96d56Sopenharmony_ci # they'll just make redundant rebindings of ._is_stopped and 10557db96d56Sopenharmony_ci # ._tstate_lock. Obscure: we rebind ._tstate_lock last so that the 10567db96d56Sopenharmony_ci # "assert self._is_stopped" in ._wait_for_tstate_lock() always works 10577db96d56Sopenharmony_ci # (the assert is executed only if ._tstate_lock is None). 10587db96d56Sopenharmony_ci # 10597db96d56Sopenharmony_ci # Special case: _main_thread releases ._tstate_lock via this 10607db96d56Sopenharmony_ci # module's _shutdown() function. 10617db96d56Sopenharmony_ci lock = self._tstate_lock 10627db96d56Sopenharmony_ci if lock is not None: 10637db96d56Sopenharmony_ci assert not lock.locked() 10647db96d56Sopenharmony_ci self._is_stopped = True 10657db96d56Sopenharmony_ci self._tstate_lock = None 10667db96d56Sopenharmony_ci if not self.daemon: 10677db96d56Sopenharmony_ci with _shutdown_locks_lock: 10687db96d56Sopenharmony_ci # Remove our lock and other released locks from _shutdown_locks 10697db96d56Sopenharmony_ci _maintain_shutdown_locks() 10707db96d56Sopenharmony_ci 10717db96d56Sopenharmony_ci def _delete(self): 10727db96d56Sopenharmony_ci "Remove current thread from the dict of currently running threads." 10737db96d56Sopenharmony_ci with _active_limbo_lock: 10747db96d56Sopenharmony_ci del _active[get_ident()] 10757db96d56Sopenharmony_ci # There must not be any python code between the previous line 10767db96d56Sopenharmony_ci # and after the lock is released. Otherwise a tracing function 10777db96d56Sopenharmony_ci # could try to acquire the lock again in the same thread, (in 10787db96d56Sopenharmony_ci # current_thread()), and would block. 10797db96d56Sopenharmony_ci 10807db96d56Sopenharmony_ci def join(self, timeout=None): 10817db96d56Sopenharmony_ci """Wait until the thread terminates. 10827db96d56Sopenharmony_ci 10837db96d56Sopenharmony_ci This blocks the calling thread until the thread whose join() method is 10847db96d56Sopenharmony_ci called terminates -- either normally or through an unhandled exception 10857db96d56Sopenharmony_ci or until the optional timeout occurs. 10867db96d56Sopenharmony_ci 10877db96d56Sopenharmony_ci When the timeout argument is present and not None, it should be a 10887db96d56Sopenharmony_ci floating point number specifying a timeout for the operation in seconds 10897db96d56Sopenharmony_ci (or fractions thereof). As join() always returns None, you must call 10907db96d56Sopenharmony_ci is_alive() after join() to decide whether a timeout happened -- if the 10917db96d56Sopenharmony_ci thread is still alive, the join() call timed out. 10927db96d56Sopenharmony_ci 10937db96d56Sopenharmony_ci When the timeout argument is not present or None, the operation will 10947db96d56Sopenharmony_ci block until the thread terminates. 10957db96d56Sopenharmony_ci 10967db96d56Sopenharmony_ci A thread can be join()ed many times. 10977db96d56Sopenharmony_ci 10987db96d56Sopenharmony_ci join() raises a RuntimeError if an attempt is made to join the current 10997db96d56Sopenharmony_ci thread as that would cause a deadlock. It is also an error to join() a 11007db96d56Sopenharmony_ci thread before it has been started and attempts to do so raises the same 11017db96d56Sopenharmony_ci exception. 11027db96d56Sopenharmony_ci 11037db96d56Sopenharmony_ci """ 11047db96d56Sopenharmony_ci if not self._initialized: 11057db96d56Sopenharmony_ci raise RuntimeError("Thread.__init__() not called") 11067db96d56Sopenharmony_ci if not self._started.is_set(): 11077db96d56Sopenharmony_ci raise RuntimeError("cannot join thread before it is started") 11087db96d56Sopenharmony_ci if self is current_thread(): 11097db96d56Sopenharmony_ci raise RuntimeError("cannot join current thread") 11107db96d56Sopenharmony_ci 11117db96d56Sopenharmony_ci if timeout is None: 11127db96d56Sopenharmony_ci self._wait_for_tstate_lock() 11137db96d56Sopenharmony_ci else: 11147db96d56Sopenharmony_ci # the behavior of a negative timeout isn't documented, but 11157db96d56Sopenharmony_ci # historically .join(timeout=x) for x<0 has acted as if timeout=0 11167db96d56Sopenharmony_ci self._wait_for_tstate_lock(timeout=max(timeout, 0)) 11177db96d56Sopenharmony_ci 11187db96d56Sopenharmony_ci def _wait_for_tstate_lock(self, block=True, timeout=-1): 11197db96d56Sopenharmony_ci # Issue #18808: wait for the thread state to be gone. 11207db96d56Sopenharmony_ci # At the end of the thread's life, after all knowledge of the thread 11217db96d56Sopenharmony_ci # is removed from C data structures, C code releases our _tstate_lock. 11227db96d56Sopenharmony_ci # This method passes its arguments to _tstate_lock.acquire(). 11237db96d56Sopenharmony_ci # If the lock is acquired, the C code is done, and self._stop() is 11247db96d56Sopenharmony_ci # called. That sets ._is_stopped to True, and ._tstate_lock to None. 11257db96d56Sopenharmony_ci lock = self._tstate_lock 11267db96d56Sopenharmony_ci if lock is None: 11277db96d56Sopenharmony_ci # already determined that the C code is done 11287db96d56Sopenharmony_ci assert self._is_stopped 11297db96d56Sopenharmony_ci return 11307db96d56Sopenharmony_ci 11317db96d56Sopenharmony_ci try: 11327db96d56Sopenharmony_ci if lock.acquire(block, timeout): 11337db96d56Sopenharmony_ci lock.release() 11347db96d56Sopenharmony_ci self._stop() 11357db96d56Sopenharmony_ci except: 11367db96d56Sopenharmony_ci if lock.locked(): 11377db96d56Sopenharmony_ci # bpo-45274: lock.acquire() acquired the lock, but the function 11387db96d56Sopenharmony_ci # was interrupted with an exception before reaching the 11397db96d56Sopenharmony_ci # lock.release(). It can happen if a signal handler raises an 11407db96d56Sopenharmony_ci # exception, like CTRL+C which raises KeyboardInterrupt. 11417db96d56Sopenharmony_ci lock.release() 11427db96d56Sopenharmony_ci self._stop() 11437db96d56Sopenharmony_ci raise 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci @property 11467db96d56Sopenharmony_ci def name(self): 11477db96d56Sopenharmony_ci """A string used for identification purposes only. 11487db96d56Sopenharmony_ci 11497db96d56Sopenharmony_ci It has no semantics. Multiple threads may be given the same name. The 11507db96d56Sopenharmony_ci initial name is set by the constructor. 11517db96d56Sopenharmony_ci 11527db96d56Sopenharmony_ci """ 11537db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() not called" 11547db96d56Sopenharmony_ci return self._name 11557db96d56Sopenharmony_ci 11567db96d56Sopenharmony_ci @name.setter 11577db96d56Sopenharmony_ci def name(self, name): 11587db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() not called" 11597db96d56Sopenharmony_ci self._name = str(name) 11607db96d56Sopenharmony_ci 11617db96d56Sopenharmony_ci @property 11627db96d56Sopenharmony_ci def ident(self): 11637db96d56Sopenharmony_ci """Thread identifier of this thread or None if it has not been started. 11647db96d56Sopenharmony_ci 11657db96d56Sopenharmony_ci This is a nonzero integer. See the get_ident() function. Thread 11667db96d56Sopenharmony_ci identifiers may be recycled when a thread exits and another thread is 11677db96d56Sopenharmony_ci created. The identifier is available even after the thread has exited. 11687db96d56Sopenharmony_ci 11697db96d56Sopenharmony_ci """ 11707db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() not called" 11717db96d56Sopenharmony_ci return self._ident 11727db96d56Sopenharmony_ci 11737db96d56Sopenharmony_ci if _HAVE_THREAD_NATIVE_ID: 11747db96d56Sopenharmony_ci @property 11757db96d56Sopenharmony_ci def native_id(self): 11767db96d56Sopenharmony_ci """Native integral thread ID of this thread, or None if it has not been started. 11777db96d56Sopenharmony_ci 11787db96d56Sopenharmony_ci This is a non-negative integer. See the get_native_id() function. 11797db96d56Sopenharmony_ci This represents the Thread ID as reported by the kernel. 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_ci """ 11827db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() not called" 11837db96d56Sopenharmony_ci return self._native_id 11847db96d56Sopenharmony_ci 11857db96d56Sopenharmony_ci def is_alive(self): 11867db96d56Sopenharmony_ci """Return whether the thread is alive. 11877db96d56Sopenharmony_ci 11887db96d56Sopenharmony_ci This method returns True just before the run() method starts until just 11897db96d56Sopenharmony_ci after the run() method terminates. See also the module function 11907db96d56Sopenharmony_ci enumerate(). 11917db96d56Sopenharmony_ci 11927db96d56Sopenharmony_ci """ 11937db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() not called" 11947db96d56Sopenharmony_ci if self._is_stopped or not self._started.is_set(): 11957db96d56Sopenharmony_ci return False 11967db96d56Sopenharmony_ci self._wait_for_tstate_lock(False) 11977db96d56Sopenharmony_ci return not self._is_stopped 11987db96d56Sopenharmony_ci 11997db96d56Sopenharmony_ci @property 12007db96d56Sopenharmony_ci def daemon(self): 12017db96d56Sopenharmony_ci """A boolean value indicating whether this thread is a daemon thread. 12027db96d56Sopenharmony_ci 12037db96d56Sopenharmony_ci This must be set before start() is called, otherwise RuntimeError is 12047db96d56Sopenharmony_ci raised. Its initial value is inherited from the creating thread; the 12057db96d56Sopenharmony_ci main thread is not a daemon thread and therefore all threads created in 12067db96d56Sopenharmony_ci the main thread default to daemon = False. 12077db96d56Sopenharmony_ci 12087db96d56Sopenharmony_ci The entire Python program exits when only daemon threads are left. 12097db96d56Sopenharmony_ci 12107db96d56Sopenharmony_ci """ 12117db96d56Sopenharmony_ci assert self._initialized, "Thread.__init__() not called" 12127db96d56Sopenharmony_ci return self._daemonic 12137db96d56Sopenharmony_ci 12147db96d56Sopenharmony_ci @daemon.setter 12157db96d56Sopenharmony_ci def daemon(self, daemonic): 12167db96d56Sopenharmony_ci if not self._initialized: 12177db96d56Sopenharmony_ci raise RuntimeError("Thread.__init__() not called") 12187db96d56Sopenharmony_ci if self._started.is_set(): 12197db96d56Sopenharmony_ci raise RuntimeError("cannot set daemon status of active thread") 12207db96d56Sopenharmony_ci self._daemonic = daemonic 12217db96d56Sopenharmony_ci 12227db96d56Sopenharmony_ci def isDaemon(self): 12237db96d56Sopenharmony_ci """Return whether this thread is a daemon. 12247db96d56Sopenharmony_ci 12257db96d56Sopenharmony_ci This method is deprecated, use the daemon attribute instead. 12267db96d56Sopenharmony_ci 12277db96d56Sopenharmony_ci """ 12287db96d56Sopenharmony_ci import warnings 12297db96d56Sopenharmony_ci warnings.warn('isDaemon() is deprecated, get the daemon attribute instead', 12307db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 12317db96d56Sopenharmony_ci return self.daemon 12327db96d56Sopenharmony_ci 12337db96d56Sopenharmony_ci def setDaemon(self, daemonic): 12347db96d56Sopenharmony_ci """Set whether this thread is a daemon. 12357db96d56Sopenharmony_ci 12367db96d56Sopenharmony_ci This method is deprecated, use the .daemon property instead. 12377db96d56Sopenharmony_ci 12387db96d56Sopenharmony_ci """ 12397db96d56Sopenharmony_ci import warnings 12407db96d56Sopenharmony_ci warnings.warn('setDaemon() is deprecated, set the daemon attribute instead', 12417db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 12427db96d56Sopenharmony_ci self.daemon = daemonic 12437db96d56Sopenharmony_ci 12447db96d56Sopenharmony_ci def getName(self): 12457db96d56Sopenharmony_ci """Return a string used for identification purposes only. 12467db96d56Sopenharmony_ci 12477db96d56Sopenharmony_ci This method is deprecated, use the name attribute instead. 12487db96d56Sopenharmony_ci 12497db96d56Sopenharmony_ci """ 12507db96d56Sopenharmony_ci import warnings 12517db96d56Sopenharmony_ci warnings.warn('getName() is deprecated, get the name attribute instead', 12527db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 12537db96d56Sopenharmony_ci return self.name 12547db96d56Sopenharmony_ci 12557db96d56Sopenharmony_ci def setName(self, name): 12567db96d56Sopenharmony_ci """Set the name string for this thread. 12577db96d56Sopenharmony_ci 12587db96d56Sopenharmony_ci This method is deprecated, use the name attribute instead. 12597db96d56Sopenharmony_ci 12607db96d56Sopenharmony_ci """ 12617db96d56Sopenharmony_ci import warnings 12627db96d56Sopenharmony_ci warnings.warn('setName() is deprecated, set the name attribute instead', 12637db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 12647db96d56Sopenharmony_ci self.name = name 12657db96d56Sopenharmony_ci 12667db96d56Sopenharmony_ci 12677db96d56Sopenharmony_citry: 12687db96d56Sopenharmony_ci from _thread import (_excepthook as excepthook, 12697db96d56Sopenharmony_ci _ExceptHookArgs as ExceptHookArgs) 12707db96d56Sopenharmony_ciexcept ImportError: 12717db96d56Sopenharmony_ci # Simple Python implementation if _thread._excepthook() is not available 12727db96d56Sopenharmony_ci from traceback import print_exception as _print_exception 12737db96d56Sopenharmony_ci from collections import namedtuple 12747db96d56Sopenharmony_ci 12757db96d56Sopenharmony_ci _ExceptHookArgs = namedtuple( 12767db96d56Sopenharmony_ci 'ExceptHookArgs', 12777db96d56Sopenharmony_ci 'exc_type exc_value exc_traceback thread') 12787db96d56Sopenharmony_ci 12797db96d56Sopenharmony_ci def ExceptHookArgs(args): 12807db96d56Sopenharmony_ci return _ExceptHookArgs(*args) 12817db96d56Sopenharmony_ci 12827db96d56Sopenharmony_ci def excepthook(args, /): 12837db96d56Sopenharmony_ci """ 12847db96d56Sopenharmony_ci Handle uncaught Thread.run() exception. 12857db96d56Sopenharmony_ci """ 12867db96d56Sopenharmony_ci if args.exc_type == SystemExit: 12877db96d56Sopenharmony_ci # silently ignore SystemExit 12887db96d56Sopenharmony_ci return 12897db96d56Sopenharmony_ci 12907db96d56Sopenharmony_ci if _sys is not None and _sys.stderr is not None: 12917db96d56Sopenharmony_ci stderr = _sys.stderr 12927db96d56Sopenharmony_ci elif args.thread is not None: 12937db96d56Sopenharmony_ci stderr = args.thread._stderr 12947db96d56Sopenharmony_ci if stderr is None: 12957db96d56Sopenharmony_ci # do nothing if sys.stderr is None and sys.stderr was None 12967db96d56Sopenharmony_ci # when the thread was created 12977db96d56Sopenharmony_ci return 12987db96d56Sopenharmony_ci else: 12997db96d56Sopenharmony_ci # do nothing if sys.stderr is None and args.thread is None 13007db96d56Sopenharmony_ci return 13017db96d56Sopenharmony_ci 13027db96d56Sopenharmony_ci if args.thread is not None: 13037db96d56Sopenharmony_ci name = args.thread.name 13047db96d56Sopenharmony_ci else: 13057db96d56Sopenharmony_ci name = get_ident() 13067db96d56Sopenharmony_ci print(f"Exception in thread {name}:", 13077db96d56Sopenharmony_ci file=stderr, flush=True) 13087db96d56Sopenharmony_ci _print_exception(args.exc_type, args.exc_value, args.exc_traceback, 13097db96d56Sopenharmony_ci file=stderr) 13107db96d56Sopenharmony_ci stderr.flush() 13117db96d56Sopenharmony_ci 13127db96d56Sopenharmony_ci 13137db96d56Sopenharmony_ci# Original value of threading.excepthook 13147db96d56Sopenharmony_ci__excepthook__ = excepthook 13157db96d56Sopenharmony_ci 13167db96d56Sopenharmony_ci 13177db96d56Sopenharmony_cidef _make_invoke_excepthook(): 13187db96d56Sopenharmony_ci # Create a local namespace to ensure that variables remain alive 13197db96d56Sopenharmony_ci # when _invoke_excepthook() is called, even if it is called late during 13207db96d56Sopenharmony_ci # Python shutdown. It is mostly needed for daemon threads. 13217db96d56Sopenharmony_ci 13227db96d56Sopenharmony_ci old_excepthook = excepthook 13237db96d56Sopenharmony_ci old_sys_excepthook = _sys.excepthook 13247db96d56Sopenharmony_ci if old_excepthook is None: 13257db96d56Sopenharmony_ci raise RuntimeError("threading.excepthook is None") 13267db96d56Sopenharmony_ci if old_sys_excepthook is None: 13277db96d56Sopenharmony_ci raise RuntimeError("sys.excepthook is None") 13287db96d56Sopenharmony_ci 13297db96d56Sopenharmony_ci sys_exc_info = _sys.exc_info 13307db96d56Sopenharmony_ci local_print = print 13317db96d56Sopenharmony_ci local_sys = _sys 13327db96d56Sopenharmony_ci 13337db96d56Sopenharmony_ci def invoke_excepthook(thread): 13347db96d56Sopenharmony_ci global excepthook 13357db96d56Sopenharmony_ci try: 13367db96d56Sopenharmony_ci hook = excepthook 13377db96d56Sopenharmony_ci if hook is None: 13387db96d56Sopenharmony_ci hook = old_excepthook 13397db96d56Sopenharmony_ci 13407db96d56Sopenharmony_ci args = ExceptHookArgs([*sys_exc_info(), thread]) 13417db96d56Sopenharmony_ci 13427db96d56Sopenharmony_ci hook(args) 13437db96d56Sopenharmony_ci except Exception as exc: 13447db96d56Sopenharmony_ci exc.__suppress_context__ = True 13457db96d56Sopenharmony_ci del exc 13467db96d56Sopenharmony_ci 13477db96d56Sopenharmony_ci if local_sys is not None and local_sys.stderr is not None: 13487db96d56Sopenharmony_ci stderr = local_sys.stderr 13497db96d56Sopenharmony_ci else: 13507db96d56Sopenharmony_ci stderr = thread._stderr 13517db96d56Sopenharmony_ci 13527db96d56Sopenharmony_ci local_print("Exception in threading.excepthook:", 13537db96d56Sopenharmony_ci file=stderr, flush=True) 13547db96d56Sopenharmony_ci 13557db96d56Sopenharmony_ci if local_sys is not None and local_sys.excepthook is not None: 13567db96d56Sopenharmony_ci sys_excepthook = local_sys.excepthook 13577db96d56Sopenharmony_ci else: 13587db96d56Sopenharmony_ci sys_excepthook = old_sys_excepthook 13597db96d56Sopenharmony_ci 13607db96d56Sopenharmony_ci sys_excepthook(*sys_exc_info()) 13617db96d56Sopenharmony_ci finally: 13627db96d56Sopenharmony_ci # Break reference cycle (exception stored in a variable) 13637db96d56Sopenharmony_ci args = None 13647db96d56Sopenharmony_ci 13657db96d56Sopenharmony_ci return invoke_excepthook 13667db96d56Sopenharmony_ci 13677db96d56Sopenharmony_ci 13687db96d56Sopenharmony_ci# The timer class was contributed by Itamar Shtull-Trauring 13697db96d56Sopenharmony_ci 13707db96d56Sopenharmony_ciclass Timer(Thread): 13717db96d56Sopenharmony_ci """Call a function after a specified number of seconds: 13727db96d56Sopenharmony_ci 13737db96d56Sopenharmony_ci t = Timer(30.0, f, args=None, kwargs=None) 13747db96d56Sopenharmony_ci t.start() 13757db96d56Sopenharmony_ci t.cancel() # stop the timer's action if it's still waiting 13767db96d56Sopenharmony_ci 13777db96d56Sopenharmony_ci """ 13787db96d56Sopenharmony_ci 13797db96d56Sopenharmony_ci def __init__(self, interval, function, args=None, kwargs=None): 13807db96d56Sopenharmony_ci Thread.__init__(self) 13817db96d56Sopenharmony_ci self.interval = interval 13827db96d56Sopenharmony_ci self.function = function 13837db96d56Sopenharmony_ci self.args = args if args is not None else [] 13847db96d56Sopenharmony_ci self.kwargs = kwargs if kwargs is not None else {} 13857db96d56Sopenharmony_ci self.finished = Event() 13867db96d56Sopenharmony_ci 13877db96d56Sopenharmony_ci def cancel(self): 13887db96d56Sopenharmony_ci """Stop the timer if it hasn't finished yet.""" 13897db96d56Sopenharmony_ci self.finished.set() 13907db96d56Sopenharmony_ci 13917db96d56Sopenharmony_ci def run(self): 13927db96d56Sopenharmony_ci self.finished.wait(self.interval) 13937db96d56Sopenharmony_ci if not self.finished.is_set(): 13947db96d56Sopenharmony_ci self.function(*self.args, **self.kwargs) 13957db96d56Sopenharmony_ci self.finished.set() 13967db96d56Sopenharmony_ci 13977db96d56Sopenharmony_ci 13987db96d56Sopenharmony_ci# Special thread class to represent the main thread 13997db96d56Sopenharmony_ci 14007db96d56Sopenharmony_ciclass _MainThread(Thread): 14017db96d56Sopenharmony_ci 14027db96d56Sopenharmony_ci def __init__(self): 14037db96d56Sopenharmony_ci Thread.__init__(self, name="MainThread", daemon=False) 14047db96d56Sopenharmony_ci self._set_tstate_lock() 14057db96d56Sopenharmony_ci self._started.set() 14067db96d56Sopenharmony_ci self._set_ident() 14077db96d56Sopenharmony_ci if _HAVE_THREAD_NATIVE_ID: 14087db96d56Sopenharmony_ci self._set_native_id() 14097db96d56Sopenharmony_ci with _active_limbo_lock: 14107db96d56Sopenharmony_ci _active[self._ident] = self 14117db96d56Sopenharmony_ci 14127db96d56Sopenharmony_ci 14137db96d56Sopenharmony_ci# Dummy thread class to represent threads not started here. 14147db96d56Sopenharmony_ci# These aren't garbage collected when they die, nor can they be waited for. 14157db96d56Sopenharmony_ci# If they invoke anything in threading.py that calls current_thread(), they 14167db96d56Sopenharmony_ci# leave an entry in the _active dict forever after. 14177db96d56Sopenharmony_ci# Their purpose is to return *something* from current_thread(). 14187db96d56Sopenharmony_ci# They are marked as daemon threads so we won't wait for them 14197db96d56Sopenharmony_ci# when we exit (conform previous semantics). 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ciclass _DummyThread(Thread): 14227db96d56Sopenharmony_ci 14237db96d56Sopenharmony_ci def __init__(self): 14247db96d56Sopenharmony_ci Thread.__init__(self, name=_newname("Dummy-%d"), daemon=True) 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ci self._started.set() 14277db96d56Sopenharmony_ci self._set_ident() 14287db96d56Sopenharmony_ci if _HAVE_THREAD_NATIVE_ID: 14297db96d56Sopenharmony_ci self._set_native_id() 14307db96d56Sopenharmony_ci with _active_limbo_lock: 14317db96d56Sopenharmony_ci _active[self._ident] = self 14327db96d56Sopenharmony_ci 14337db96d56Sopenharmony_ci def _stop(self): 14347db96d56Sopenharmony_ci pass 14357db96d56Sopenharmony_ci 14367db96d56Sopenharmony_ci def is_alive(self): 14377db96d56Sopenharmony_ci assert not self._is_stopped and self._started.is_set() 14387db96d56Sopenharmony_ci return True 14397db96d56Sopenharmony_ci 14407db96d56Sopenharmony_ci def join(self, timeout=None): 14417db96d56Sopenharmony_ci assert False, "cannot join a dummy thread" 14427db96d56Sopenharmony_ci 14437db96d56Sopenharmony_ci 14447db96d56Sopenharmony_ci# Global API functions 14457db96d56Sopenharmony_ci 14467db96d56Sopenharmony_cidef current_thread(): 14477db96d56Sopenharmony_ci """Return the current Thread object, corresponding to the caller's thread of control. 14487db96d56Sopenharmony_ci 14497db96d56Sopenharmony_ci If the caller's thread of control was not created through the threading 14507db96d56Sopenharmony_ci module, a dummy thread object with limited functionality is returned. 14517db96d56Sopenharmony_ci 14527db96d56Sopenharmony_ci """ 14537db96d56Sopenharmony_ci try: 14547db96d56Sopenharmony_ci return _active[get_ident()] 14557db96d56Sopenharmony_ci except KeyError: 14567db96d56Sopenharmony_ci return _DummyThread() 14577db96d56Sopenharmony_ci 14587db96d56Sopenharmony_cidef currentThread(): 14597db96d56Sopenharmony_ci """Return the current Thread object, corresponding to the caller's thread of control. 14607db96d56Sopenharmony_ci 14617db96d56Sopenharmony_ci This function is deprecated, use current_thread() instead. 14627db96d56Sopenharmony_ci 14637db96d56Sopenharmony_ci """ 14647db96d56Sopenharmony_ci import warnings 14657db96d56Sopenharmony_ci warnings.warn('currentThread() is deprecated, use current_thread() instead', 14667db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 14677db96d56Sopenharmony_ci return current_thread() 14687db96d56Sopenharmony_ci 14697db96d56Sopenharmony_cidef active_count(): 14707db96d56Sopenharmony_ci """Return the number of Thread objects currently alive. 14717db96d56Sopenharmony_ci 14727db96d56Sopenharmony_ci The returned count is equal to the length of the list returned by 14737db96d56Sopenharmony_ci enumerate(). 14747db96d56Sopenharmony_ci 14757db96d56Sopenharmony_ci """ 14767db96d56Sopenharmony_ci with _active_limbo_lock: 14777db96d56Sopenharmony_ci return len(_active) + len(_limbo) 14787db96d56Sopenharmony_ci 14797db96d56Sopenharmony_cidef activeCount(): 14807db96d56Sopenharmony_ci """Return the number of Thread objects currently alive. 14817db96d56Sopenharmony_ci 14827db96d56Sopenharmony_ci This function is deprecated, use active_count() instead. 14837db96d56Sopenharmony_ci 14847db96d56Sopenharmony_ci """ 14857db96d56Sopenharmony_ci import warnings 14867db96d56Sopenharmony_ci warnings.warn('activeCount() is deprecated, use active_count() instead', 14877db96d56Sopenharmony_ci DeprecationWarning, stacklevel=2) 14887db96d56Sopenharmony_ci return active_count() 14897db96d56Sopenharmony_ci 14907db96d56Sopenharmony_cidef _enumerate(): 14917db96d56Sopenharmony_ci # Same as enumerate(), but without the lock. Internal use only. 14927db96d56Sopenharmony_ci return list(_active.values()) + list(_limbo.values()) 14937db96d56Sopenharmony_ci 14947db96d56Sopenharmony_cidef enumerate(): 14957db96d56Sopenharmony_ci """Return a list of all Thread objects currently alive. 14967db96d56Sopenharmony_ci 14977db96d56Sopenharmony_ci The list includes daemonic threads, dummy thread objects created by 14987db96d56Sopenharmony_ci current_thread(), and the main thread. It excludes terminated threads and 14997db96d56Sopenharmony_ci threads that have not yet been started. 15007db96d56Sopenharmony_ci 15017db96d56Sopenharmony_ci """ 15027db96d56Sopenharmony_ci with _active_limbo_lock: 15037db96d56Sopenharmony_ci return list(_active.values()) + list(_limbo.values()) 15047db96d56Sopenharmony_ci 15057db96d56Sopenharmony_ci 15067db96d56Sopenharmony_ci_threading_atexits = [] 15077db96d56Sopenharmony_ci_SHUTTING_DOWN = False 15087db96d56Sopenharmony_ci 15097db96d56Sopenharmony_cidef _register_atexit(func, *arg, **kwargs): 15107db96d56Sopenharmony_ci """CPython internal: register *func* to be called before joining threads. 15117db96d56Sopenharmony_ci 15127db96d56Sopenharmony_ci The registered *func* is called with its arguments just before all 15137db96d56Sopenharmony_ci non-daemon threads are joined in `_shutdown()`. It provides a similar 15147db96d56Sopenharmony_ci purpose to `atexit.register()`, but its functions are called prior to 15157db96d56Sopenharmony_ci threading shutdown instead of interpreter shutdown. 15167db96d56Sopenharmony_ci 15177db96d56Sopenharmony_ci For similarity to atexit, the registered functions are called in reverse. 15187db96d56Sopenharmony_ci """ 15197db96d56Sopenharmony_ci if _SHUTTING_DOWN: 15207db96d56Sopenharmony_ci raise RuntimeError("can't register atexit after shutdown") 15217db96d56Sopenharmony_ci 15227db96d56Sopenharmony_ci call = functools.partial(func, *arg, **kwargs) 15237db96d56Sopenharmony_ci _threading_atexits.append(call) 15247db96d56Sopenharmony_ci 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_cifrom _thread import stack_size 15277db96d56Sopenharmony_ci 15287db96d56Sopenharmony_ci# Create the main thread object, 15297db96d56Sopenharmony_ci# and make it available for the interpreter 15307db96d56Sopenharmony_ci# (Py_Main) as threading._shutdown. 15317db96d56Sopenharmony_ci 15327db96d56Sopenharmony_ci_main_thread = _MainThread() 15337db96d56Sopenharmony_ci 15347db96d56Sopenharmony_cidef _shutdown(): 15357db96d56Sopenharmony_ci """ 15367db96d56Sopenharmony_ci Wait until the Python thread state of all non-daemon threads get deleted. 15377db96d56Sopenharmony_ci """ 15387db96d56Sopenharmony_ci # Obscure: other threads may be waiting to join _main_thread. That's 15397db96d56Sopenharmony_ci # dubious, but some code does it. We can't wait for C code to release 15407db96d56Sopenharmony_ci # the main thread's tstate_lock - that won't happen until the interpreter 15417db96d56Sopenharmony_ci # is nearly dead. So we release it here. Note that just calling _stop() 15427db96d56Sopenharmony_ci # isn't enough: other threads may already be waiting on _tstate_lock. 15437db96d56Sopenharmony_ci if _main_thread._is_stopped: 15447db96d56Sopenharmony_ci # _shutdown() was already called 15457db96d56Sopenharmony_ci return 15467db96d56Sopenharmony_ci 15477db96d56Sopenharmony_ci global _SHUTTING_DOWN 15487db96d56Sopenharmony_ci _SHUTTING_DOWN = True 15497db96d56Sopenharmony_ci 15507db96d56Sopenharmony_ci # Call registered threading atexit functions before threads are joined. 15517db96d56Sopenharmony_ci # Order is reversed, similar to atexit. 15527db96d56Sopenharmony_ci for atexit_call in reversed(_threading_atexits): 15537db96d56Sopenharmony_ci atexit_call() 15547db96d56Sopenharmony_ci 15557db96d56Sopenharmony_ci # Main thread 15567db96d56Sopenharmony_ci if _main_thread.ident == get_ident(): 15577db96d56Sopenharmony_ci tlock = _main_thread._tstate_lock 15587db96d56Sopenharmony_ci # The main thread isn't finished yet, so its thread state lock can't 15597db96d56Sopenharmony_ci # have been released. 15607db96d56Sopenharmony_ci assert tlock is not None 15617db96d56Sopenharmony_ci assert tlock.locked() 15627db96d56Sopenharmony_ci tlock.release() 15637db96d56Sopenharmony_ci _main_thread._stop() 15647db96d56Sopenharmony_ci else: 15657db96d56Sopenharmony_ci # bpo-1596321: _shutdown() must be called in the main thread. 15667db96d56Sopenharmony_ci # If the threading module was not imported by the main thread, 15677db96d56Sopenharmony_ci # _main_thread is the thread which imported the threading module. 15687db96d56Sopenharmony_ci # In this case, ignore _main_thread, similar behavior than for threads 15697db96d56Sopenharmony_ci # spawned by C libraries or using _thread.start_new_thread(). 15707db96d56Sopenharmony_ci pass 15717db96d56Sopenharmony_ci 15727db96d56Sopenharmony_ci # Join all non-deamon threads 15737db96d56Sopenharmony_ci while True: 15747db96d56Sopenharmony_ci with _shutdown_locks_lock: 15757db96d56Sopenharmony_ci locks = list(_shutdown_locks) 15767db96d56Sopenharmony_ci _shutdown_locks.clear() 15777db96d56Sopenharmony_ci 15787db96d56Sopenharmony_ci if not locks: 15797db96d56Sopenharmony_ci break 15807db96d56Sopenharmony_ci 15817db96d56Sopenharmony_ci for lock in locks: 15827db96d56Sopenharmony_ci # mimic Thread.join() 15837db96d56Sopenharmony_ci lock.acquire() 15847db96d56Sopenharmony_ci lock.release() 15857db96d56Sopenharmony_ci 15867db96d56Sopenharmony_ci # new threads can be spawned while we were waiting for the other 15877db96d56Sopenharmony_ci # threads to complete 15887db96d56Sopenharmony_ci 15897db96d56Sopenharmony_ci 15907db96d56Sopenharmony_cidef main_thread(): 15917db96d56Sopenharmony_ci """Return the main thread object. 15927db96d56Sopenharmony_ci 15937db96d56Sopenharmony_ci In normal conditions, the main thread is the thread from which the 15947db96d56Sopenharmony_ci Python interpreter was started. 15957db96d56Sopenharmony_ci """ 15967db96d56Sopenharmony_ci return _main_thread 15977db96d56Sopenharmony_ci 15987db96d56Sopenharmony_ci# get thread-local implementation, either from the thread 15997db96d56Sopenharmony_ci# module, or from the python fallback 16007db96d56Sopenharmony_ci 16017db96d56Sopenharmony_citry: 16027db96d56Sopenharmony_ci from _thread import _local as local 16037db96d56Sopenharmony_ciexcept ImportError: 16047db96d56Sopenharmony_ci from _threading_local import local 16057db96d56Sopenharmony_ci 16067db96d56Sopenharmony_ci 16077db96d56Sopenharmony_cidef _after_fork(): 16087db96d56Sopenharmony_ci """ 16097db96d56Sopenharmony_ci Cleanup threading module state that should not exist after a fork. 16107db96d56Sopenharmony_ci """ 16117db96d56Sopenharmony_ci # Reset _active_limbo_lock, in case we forked while the lock was held 16127db96d56Sopenharmony_ci # by another (non-forked) thread. http://bugs.python.org/issue874900 16137db96d56Sopenharmony_ci global _active_limbo_lock, _main_thread 16147db96d56Sopenharmony_ci global _shutdown_locks_lock, _shutdown_locks 16157db96d56Sopenharmony_ci _active_limbo_lock = RLock() 16167db96d56Sopenharmony_ci 16177db96d56Sopenharmony_ci # fork() only copied the current thread; clear references to others. 16187db96d56Sopenharmony_ci new_active = {} 16197db96d56Sopenharmony_ci 16207db96d56Sopenharmony_ci try: 16217db96d56Sopenharmony_ci current = _active[get_ident()] 16227db96d56Sopenharmony_ci except KeyError: 16237db96d56Sopenharmony_ci # fork() was called in a thread which was not spawned 16247db96d56Sopenharmony_ci # by threading.Thread. For example, a thread spawned 16257db96d56Sopenharmony_ci # by thread.start_new_thread(). 16267db96d56Sopenharmony_ci current = _MainThread() 16277db96d56Sopenharmony_ci 16287db96d56Sopenharmony_ci _main_thread = current 16297db96d56Sopenharmony_ci 16307db96d56Sopenharmony_ci # reset _shutdown() locks: threads re-register their _tstate_lock below 16317db96d56Sopenharmony_ci _shutdown_locks_lock = _allocate_lock() 16327db96d56Sopenharmony_ci _shutdown_locks = set() 16337db96d56Sopenharmony_ci 16347db96d56Sopenharmony_ci with _active_limbo_lock: 16357db96d56Sopenharmony_ci # Dangling thread instances must still have their locks reset, 16367db96d56Sopenharmony_ci # because someone may join() them. 16377db96d56Sopenharmony_ci threads = set(_enumerate()) 16387db96d56Sopenharmony_ci threads.update(_dangling) 16397db96d56Sopenharmony_ci for thread in threads: 16407db96d56Sopenharmony_ci # Any lock/condition variable may be currently locked or in an 16417db96d56Sopenharmony_ci # invalid state, so we reinitialize them. 16427db96d56Sopenharmony_ci if thread is current: 16437db96d56Sopenharmony_ci # There is only one active thread. We reset the ident to 16447db96d56Sopenharmony_ci # its new value since it can have changed. 16457db96d56Sopenharmony_ci thread._reset_internal_locks(True) 16467db96d56Sopenharmony_ci ident = get_ident() 16477db96d56Sopenharmony_ci thread._ident = ident 16487db96d56Sopenharmony_ci new_active[ident] = thread 16497db96d56Sopenharmony_ci else: 16507db96d56Sopenharmony_ci # All the others are already stopped. 16517db96d56Sopenharmony_ci thread._reset_internal_locks(False) 16527db96d56Sopenharmony_ci thread._stop() 16537db96d56Sopenharmony_ci 16547db96d56Sopenharmony_ci _limbo.clear() 16557db96d56Sopenharmony_ci _active.clear() 16567db96d56Sopenharmony_ci _active.update(new_active) 16577db96d56Sopenharmony_ci assert len(_active) == 1 16587db96d56Sopenharmony_ci 16597db96d56Sopenharmony_ci 16607db96d56Sopenharmony_ciif hasattr(_os, "register_at_fork"): 16617db96d56Sopenharmony_ci _os.register_at_fork(after_in_child=_after_fork) 1662