Show More
Commit Description:
Merge pull request #17 from nattee/master...
Commit Description:
Merge pull request #17 from nattee/master
upgrade to current working snapshot
References:
File last commit:
Show/Diff file:
Action:
lib/assets/Lib/threading.py
| 1293 lines
| 45.8 KiB
| text/x-python
| PythonLexer
|
r584 | """Thread module emulating a subset of Java's threading model.""" | |||
import sys as _sys | ||||
import _thread | ||||
from time import sleep as _sleep | ||||
try: | ||||
from time import monotonic as _time | ||||
except ImportError: | ||||
from time import time as _time | ||||
from traceback import format_exc as _format_exc | ||||
from _weakrefset import WeakSet | ||||
# Note regarding PEP 8 compliant names | ||||
# This threading model was originally inspired by Java, and inherited | ||||
# the convention of camelCase function and method names from that | ||||
# language. Those original names are not in any imminent danger of | ||||
# being deprecated (even for Py3k),so this module provides them as an | ||||
# alias for the PEP 8 compliant names | ||||
# Note that using the new PEP 8 compliant names facilitates substitution | ||||
# with the multiprocessing module, which doesn't provide the old | ||||
# Java inspired names. | ||||
__all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event', | ||||
'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier', | ||||
'Timer', 'ThreadError', 'setprofile', 'settrace', 'local', 'stack_size'] | ||||
# Rename some stuff so "from threading import *" is safe | ||||
_start_new_thread = _thread.start_new_thread | ||||
_allocate_lock = _thread.allocate_lock | ||||
get_ident = _thread.get_ident | ||||
ThreadError = _thread.error | ||||
try: | ||||
_CRLock = _thread.RLock | ||||
except AttributeError: | ||||
_CRLock = None | ||||
TIMEOUT_MAX = _thread.TIMEOUT_MAX | ||||
del _thread | ||||
# Support for profile and trace hooks | ||||
_profile_hook = None | ||||
_trace_hook = None | ||||
def setprofile(func): | ||||
"""Set a profile function for all threads started from the threading module. | ||||
The func will be passed to sys.setprofile() for each thread, before its | ||||
run() method is called. | ||||
""" | ||||
global _profile_hook | ||||
_profile_hook = func | ||||
def settrace(func): | ||||
"""Set a trace function for all threads started from the threading module. | ||||
The func will be passed to sys.settrace() for each thread, before its run() | ||||
method is called. | ||||
""" | ||||
global _trace_hook | ||||
_trace_hook = func | ||||
# Synchronization classes | ||||
Lock = _allocate_lock | ||||
def RLock(*args, **kwargs): | ||||
"""Factory function that returns a new reentrant lock. | ||||
A reentrant lock must be released by the thread that acquired it. Once a | ||||
thread has acquired a reentrant lock, the same thread may acquire it again | ||||
without blocking; the thread must release it once for each time it has | ||||
acquired it. | ||||
""" | ||||
if _CRLock is None: | ||||
return _PyRLock(*args, **kwargs) | ||||
return _CRLock(*args, **kwargs) | ||||
class _RLock: | ||||
"""This class implements reentrant lock objects. | ||||
A reentrant lock must be released by the thread that acquired it. Once a | ||||
thread has acquired a reentrant lock, the same thread may acquire it | ||||
again without blocking; the thread must release it once for each time it | ||||
has acquired it. | ||||
""" | ||||
def __init__(self): | ||||
self._block = _allocate_lock() | ||||
self._owner = None | ||||
self._count = 0 | ||||
def __repr__(self): | ||||
owner = self._owner | ||||
try: | ||||
owner = _active[owner].name | ||||
except KeyError: | ||||
pass | ||||
return "<%s owner=%r count=%d>" % ( | ||||
self.__class__.__name__, owner, self._count) | ||||
def acquire(self, blocking=True, timeout=-1): | ||||
"""Acquire a lock, blocking or non-blocking. | ||||
When invoked without arguments: if this thread already owns the lock, | ||||
increment the recursion level by one, and return immediately. Otherwise, | ||||
if another thread owns the lock, block until the lock is unlocked. Once | ||||
the lock is unlocked (not owned by any thread), then grab ownership, set | ||||
the recursion level to one, and return. If more than one thread is | ||||
blocked waiting until the lock is unlocked, only one at a time will be | ||||
able to grab ownership of the lock. There is no return value in this | ||||
case. | ||||
When invoked with the blocking argument set to true, do the same thing | ||||
as when called without arguments, and return true. | ||||
When invoked with the blocking argument set to false, do not block. If a | ||||
call without an argument would block, return false immediately; | ||||
otherwise, do the same thing as when called without arguments, and | ||||
return true. | ||||
When invoked with the floating-point timeout argument set to a positive | ||||
value, block for at most the number of seconds specified by timeout | ||||
and as long as the lock cannot be acquired. Return true if the lock has | ||||
been acquired, false if the timeout has elapsed. | ||||
""" | ||||
me = get_ident() | ||||
if self._owner == me: | ||||
self._count = self._count + 1 | ||||
return 1 | ||||
rc = self._block.acquire(blocking, timeout) | ||||
if rc: | ||||
self._owner = me | ||||
self._count = 1 | ||||
return rc | ||||
__enter__ = acquire | ||||
def release(self): | ||||
"""Release a lock, decrementing the recursion level. | ||||
If after the decrement it is zero, reset the lock to unlocked (not owned | ||||
by any thread), and if any other threads are blocked waiting for the | ||||
lock to become unlocked, allow exactly one of them to proceed. If after | ||||
the decrement the recursion level is still nonzero, the lock remains | ||||
locked and owned by the calling thread. | ||||
Only call this method when the calling thread owns the lock. A | ||||
RuntimeError is raised if this method is called when the lock is | ||||
unlocked. | ||||
There is no return value. | ||||
""" | ||||
if self._owner != get_ident(): | ||||
raise RuntimeError("cannot release un-acquired lock") | ||||
self._count = count = self._count - 1 | ||||
if not count: | ||||
self._owner = None | ||||
self._block.release() | ||||
def __exit__(self, t, v, tb): | ||||
self.release() | ||||
# Internal methods used by condition variables | ||||
def _acquire_restore(self, state): | ||||
self._block.acquire() | ||||
self._count, self._owner = state | ||||
def _release_save(self): | ||||
if self._count == 0: | ||||
raise RuntimeError("cannot release un-acquired lock") | ||||
count = self._count | ||||
self._count = 0 | ||||
owner = self._owner | ||||
self._owner = None | ||||
self._block.release() | ||||
return (count, owner) | ||||
def _is_owned(self): | ||||
return self._owner == get_ident() | ||||
_PyRLock = _RLock | ||||
class Condition: | ||||
"""Class that implements a condition variable. | ||||
A condition variable allows one or more threads to wait until they are | ||||
notified by another thread. | ||||
If the lock argument is given and not None, it must be a Lock or RLock | ||||
object, and it is used as the underlying lock. Otherwise, a new RLock object | ||||
is created and used as the underlying lock. | ||||
""" | ||||
def __init__(self, lock=None): | ||||
if lock is None: | ||||
lock = RLock() | ||||
self._lock = lock | ||||
# Export the lock's acquire() and release() methods | ||||
self.acquire = lock.acquire | ||||
self.release = lock.release | ||||
# If the lock defines _release_save() and/or _acquire_restore(), | ||||
# these override the default implementations (which just call | ||||
# release() and acquire() on the lock). Ditto for _is_owned(). | ||||
try: | ||||
self._release_save = lock._release_save | ||||
except AttributeError: | ||||
pass | ||||
try: | ||||
self._acquire_restore = lock._acquire_restore | ||||
except AttributeError: | ||||
pass | ||||
try: | ||||
self._is_owned = lock._is_owned | ||||
except AttributeError: | ||||
pass | ||||
self._waiters = [] | ||||
def __enter__(self): | ||||
return self._lock.__enter__() | ||||
def __exit__(self, *args): | ||||
return self._lock.__exit__(*args) | ||||
def __repr__(self): | ||||
return "<Condition(%s, %d)>" % (self._lock, len(self._waiters)) | ||||
def _release_save(self): | ||||
self._lock.release() # No state to save | ||||
def _acquire_restore(self, x): | ||||
self._lock.acquire() # Ignore saved state | ||||
def _is_owned(self): | ||||
# Return True if lock is owned by current_thread. | ||||
# This method is called only if __lock doesn't have _is_owned(). | ||||
if self._lock.acquire(0): | ||||
self._lock.release() | ||||
return False | ||||
else: | ||||
return True | ||||
def wait(self, timeout=None): | ||||
"""Wait until notified or until a timeout occurs. | ||||
If the calling thread has not acquired the lock when this method is | ||||
called, a RuntimeError is raised. | ||||
This method releases the underlying lock, and then blocks until it is | ||||
awakened by a notify() or notify_all() call for the same condition | ||||
variable in another thread, or until the optional timeout occurs. Once | ||||
awakened or timed out, it re-acquires the lock and returns. | ||||
When the timeout argument is present and not None, it should be a | ||||
floating point number specifying a timeout for the operation in seconds | ||||
(or fractions thereof). | ||||
When the underlying lock is an RLock, it is not released using its | ||||
release() method, since this may not actually unlock the lock when it | ||||
was acquired multiple times recursively. Instead, an internal interface | ||||
of the RLock class is used, which really unlocks it even when it has | ||||
been recursively acquired several times. Another internal interface is | ||||
then used to restore the recursion level when the lock is reacquired. | ||||
""" | ||||
if not self._is_owned(): | ||||
raise RuntimeError("cannot wait on un-acquired lock") | ||||
waiter = _allocate_lock() | ||||
waiter.acquire() | ||||
self._waiters.append(waiter) | ||||
saved_state = self._release_save() | ||||
try: # restore state no matter what (e.g., KeyboardInterrupt) | ||||
if timeout is None: | ||||
waiter.acquire() | ||||
gotit = True | ||||
else: | ||||
if timeout > 0: | ||||
gotit = waiter.acquire(True, timeout) | ||||
else: | ||||
gotit = waiter.acquire(False) | ||||
if not gotit: | ||||
try: | ||||
self._waiters.remove(waiter) | ||||
except ValueError: | ||||
pass | ||||
return gotit | ||||
finally: | ||||
self._acquire_restore(saved_state) | ||||
def wait_for(self, predicate, timeout=None): | ||||
"""Wait until a condition evaluates to True. | ||||
predicate should be a callable which result will be interpreted as a | ||||
boolean value. A timeout may be provided giving the maximum time to | ||||
wait. | ||||
""" | ||||
endtime = None | ||||
waittime = timeout | ||||
result = predicate() | ||||
while not result: | ||||
if waittime is not None: | ||||
if endtime is None: | ||||
endtime = _time() + waittime | ||||
else: | ||||
waittime = endtime - _time() | ||||
if waittime <= 0: | ||||
break | ||||
self.wait(waittime) | ||||
result = predicate() | ||||
return result | ||||
def notify(self, n=1): | ||||
"""Wake up one or more threads waiting on this condition, if any. | ||||
If the calling thread has not acquired the lock when this method is | ||||
called, a RuntimeError is raised. | ||||
This method wakes up at most n of the threads waiting for the condition | ||||
variable; it is a no-op if no threads are waiting. | ||||
""" | ||||
if not self._is_owned(): | ||||
raise RuntimeError("cannot notify on un-acquired lock") | ||||
__waiters = self._waiters | ||||
waiters = __waiters[:n] | ||||
if not waiters: | ||||
return | ||||
for waiter in waiters: | ||||
waiter.release() | ||||
try: | ||||
__waiters.remove(waiter) | ||||
except ValueError: | ||||
pass | ||||
def notify_all(self): | ||||
"""Wake up all threads waiting on this condition. | ||||
If the calling thread has not acquired the lock when this method | ||||
is called, a RuntimeError is raised. | ||||
""" | ||||
self.notify(len(self._waiters)) | ||||
notifyAll = notify_all | ||||
class Semaphore: | ||||
"""This class implements semaphore objects. | ||||
Semaphores manage a counter representing the number of release() calls minus | ||||
the number of acquire() calls, plus an initial value. The acquire() method | ||||
blocks if necessary until it can return without making the counter | ||||
negative. If not given, value defaults to 1. | ||||
""" | ||||
# After Tim Peters' semaphore class, but not quite the same (no maximum) | ||||
def __init__(self, value=1): | ||||
if value < 0: | ||||
raise ValueError("semaphore initial value must be >= 0") | ||||
self._cond = Condition(Lock()) | ||||
self._value = value | ||||
def acquire(self, blocking=True, timeout=None): | ||||
"""Acquire a semaphore, decrementing the internal counter by one. | ||||
When invoked without arguments: if the internal counter is larger than | ||||
zero on entry, decrement it by one and return immediately. If it is zero | ||||
on entry, block, waiting until some other thread has called release() to | ||||
make it larger than zero. This is done with proper interlocking so that | ||||
if multiple acquire() calls are blocked, release() will wake exactly one | ||||
of them up. The implementation may pick one at random, so the order in | ||||
which blocked threads are awakened should not be relied on. There is no | ||||
return value in this case. | ||||
When invoked with blocking set to true, do the same thing as when called | ||||
without arguments, and return true. | ||||
When invoked with blocking set to false, do not block. If a call without | ||||
an argument would block, return false immediately; otherwise, do the | ||||
same thing as when called without arguments, and return true. | ||||
When invoked with a timeout other than None, it will block for at | ||||
most timeout seconds. If acquire does not complete successfully in | ||||
that interval, return false. Return true otherwise. | ||||
""" | ||||
if not blocking and timeout is not None: | ||||
raise ValueError("can't specify timeout for non-blocking acquire") | ||||
rc = False | ||||
endtime = None | ||||
with self._cond: | ||||
while self._value == 0: | ||||
if not blocking: | ||||
break | ||||
if timeout is not None: | ||||
if endtime is None: | ||||
endtime = _time() + timeout | ||||
else: | ||||
timeout = endtime - _time() | ||||
if timeout <= 0: | ||||
break | ||||
self._cond.wait(timeout) | ||||
else: | ||||
self._value = self._value - 1 | ||||
rc = True | ||||
return rc | ||||
__enter__ = acquire | ||||
def release(self): | ||||
"""Release a semaphore, incrementing the internal counter by one. | ||||
When the counter is zero on entry and another thread is waiting for it | ||||
to become larger than zero again, wake up that thread. | ||||
""" | ||||
with self._cond: | ||||
self._value = self._value + 1 | ||||
self._cond.notify() | ||||
def __exit__(self, t, v, tb): | ||||
self.release() | ||||
class BoundedSemaphore(Semaphore): | ||||
"""Implements a bounded semaphore. | ||||
A bounded semaphore checks to make sure its current value doesn't exceed its | ||||
initial value. If it does, ValueError is raised. In most situations | ||||
semaphores are used to guard resources with limited capacity. | ||||
If the semaphore is released too many times it's a sign of a bug. If not | ||||
given, value defaults to 1. | ||||
Like regular semaphores, bounded semaphores manage a counter representing | ||||
the number of release() calls minus the number of acquire() calls, plus an | ||||
initial value. The acquire() method blocks if necessary until it can return | ||||
without making the counter negative. If not given, value defaults to 1. | ||||
""" | ||||
def __init__(self, value=1): | ||||
Semaphore.__init__(self, value) | ||||
self._initial_value = value | ||||
def release(self): | ||||
"""Release a semaphore, incrementing the internal counter by one. | ||||
When the counter is zero on entry and another thread is waiting for it | ||||
to become larger than zero again, wake up that thread. | ||||
If the number of releases exceeds the number of acquires, | ||||
raise a ValueError. | ||||
""" | ||||
with self._cond: | ||||
if self._value >= self._initial_value: | ||||
raise ValueError("Semaphore released too many times") | ||||
self._value += 1 | ||||
self._cond.notify() | ||||
class Event: | ||||
"""Class implementing event objects. | ||||
Events manage a flag that can be set to true with the set() method and reset | ||||
to false with the clear() method. The wait() method blocks until the flag is | ||||
true. The flag is initially false. | ||||
""" | ||||
# After Tim Peters' event class (without is_posted()) | ||||
def __init__(self): | ||||
self._cond = Condition(Lock()) | ||||
self._flag = False | ||||
def _reset_internal_locks(self): | ||||
# private! called by Thread._reset_internal_locks by _after_fork() | ||||
self._cond.__init__() | ||||
def is_set(self): | ||||
"""Return true if and only if the internal flag is true.""" | ||||
return self._flag | ||||
isSet = is_set | ||||
def set(self): | ||||
"""Set the internal flag to true. | ||||
All threads waiting for it to become true are awakened. Threads | ||||
that call wait() once the flag is true will not block at all. | ||||
""" | ||||
self._cond.acquire() | ||||
try: | ||||
self._flag = True | ||||
self._cond.notify_all() | ||||
finally: | ||||
self._cond.release() | ||||
def clear(self): | ||||
"""Reset the internal flag to false. | ||||
Subsequently, threads calling wait() will block until set() is called to | ||||
set the internal flag to true again. | ||||
""" | ||||
self._cond.acquire() | ||||
try: | ||||
self._flag = False | ||||
finally: | ||||
self._cond.release() | ||||
def wait(self, timeout=None): | ||||
"""Block until the internal flag is true. | ||||
If the internal flag is true on entry, return immediately. Otherwise, | ||||
block until another thread calls set() to set the flag to true, or until | ||||
the optional timeout occurs. | ||||
When the timeout argument is present and not None, it should be a | ||||
floating point number specifying a timeout for the operation in seconds | ||||
(or fractions thereof). | ||||
This method returns the internal flag on exit, so it will always return | ||||
True except if a timeout is given and the operation times out. | ||||
""" | ||||
self._cond.acquire() | ||||
try: | ||||
signaled = self._flag | ||||
if not signaled: | ||||
signaled = self._cond.wait(timeout) | ||||
return signaled | ||||
finally: | ||||
self._cond.release() | ||||
# A barrier class. Inspired in part by the pthread_barrier_* api and | ||||
# the CyclicBarrier class from Java. See | ||||
# http://sourceware.org/pthreads-win32/manual/pthread_barrier_init.html and | ||||
# http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ | ||||
# CyclicBarrier.html | ||||
# for information. | ||||
# We maintain two main states, 'filling' and 'draining' enabling the barrier | ||||
# to be cyclic. Threads are not allowed into it until it has fully drained | ||||
# since the previous cycle. In addition, a 'resetting' state exists which is | ||||
# similar to 'draining' except that threads leave with a BrokenBarrierError, | ||||
# and a 'broken' state in which all threads get the exception. | ||||
class Barrier: | ||||
"""Implements a Barrier. | ||||
Useful for synchronizing a fixed number of threads at known synchronization | ||||
points. Threads block on 'wait()' and are simultaneously once they have all | ||||
made that call. | ||||
""" | ||||
def __init__(self, parties, action=None, timeout=None): | ||||
"""Create a barrier, initialised to 'parties' threads. | ||||
'action' is a callable which, when supplied, will be called by one of | ||||
the threads after they have all entered the barrier and just prior to | ||||
releasing them all. If a 'timeout' is provided, it is uses as the | ||||
default for all subsequent 'wait()' calls. | ||||
""" | ||||
self._cond = Condition(Lock()) | ||||
self._action = action | ||||
self._timeout = timeout | ||||
self._parties = parties | ||||
self._state = 0 #0 filling, 1, draining, -1 resetting, -2 broken | ||||
self._count = 0 | ||||
def wait(self, timeout=None): | ||||
"""Wait for the barrier. | ||||
When the specified number of threads have started waiting, they are all | ||||
simultaneously awoken. If an 'action' was provided for the barrier, one | ||||
of the threads will have executed that callback prior to returning. | ||||
Returns an individual index number from 0 to 'parties-1'. | ||||
""" | ||||
if timeout is None: | ||||
timeout = self._timeout | ||||
with self._cond: | ||||
self._enter() # Block while the barrier drains. | ||||
index = self._count | ||||
self._count += 1 | ||||
try: | ||||
if index + 1 == self._parties: | ||||
# We release the barrier | ||||
self._release() | ||||
else: | ||||
# We wait until someone releases us | ||||
self._wait(timeout) | ||||
return index | ||||
finally: | ||||
self._count -= 1 | ||||
# Wake up any threads waiting for barrier to drain. | ||||
self._exit() | ||||
# Block until the barrier is ready for us, or raise an exception | ||||
# if it is broken. | ||||
def _enter(self): | ||||
while self._state in (-1, 1): | ||||
# It is draining or resetting, wait until done | ||||
self._cond.wait() | ||||
#see if the barrier is in a broken state | ||||
if self._state < 0: | ||||
raise BrokenBarrierError | ||||
assert self._state == 0 | ||||
# Optionally run the 'action' and release the threads waiting | ||||
# in the barrier. | ||||
def _release(self): | ||||
try: | ||||
if self._action: | ||||
self._action() | ||||
# enter draining state | ||||
self._state = 1 | ||||
self._cond.notify_all() | ||||
except: | ||||
#an exception during the _action handler. Break and reraise | ||||
self._break() | ||||
raise | ||||
# Wait in the barrier until we are relased. Raise an exception | ||||
# if the barrier is reset or broken. | ||||
def _wait(self, timeout): | ||||
if not self._cond.wait_for(lambda : self._state != 0, timeout): | ||||
#timed out. Break the barrier | ||||
self._break() | ||||
raise BrokenBarrierError | ||||
if self._state < 0: | ||||
raise BrokenBarrierError | ||||
assert self._state == 1 | ||||
# If we are the last thread to exit the barrier, signal any threads | ||||
# waiting for the barrier to drain. | ||||
def _exit(self): | ||||
if self._count == 0: | ||||
if self._state in (-1, 1): | ||||
#resetting or draining | ||||
self._state = 0 | ||||
self._cond.notify_all() | ||||
def reset(self): | ||||
"""Reset the barrier to the initial state. | ||||
Any threads currently waiting will get the BrokenBarrier exception | ||||
raised. | ||||
""" | ||||
with self._cond: | ||||
if self._count > 0: | ||||
if self._state == 0: | ||||
#reset the barrier, waking up threads | ||||
self._state = -1 | ||||
elif self._state == -2: | ||||
#was broken, set it to reset state | ||||
#which clears when the last thread exits | ||||
self._state = -1 | ||||
else: | ||||
self._state = 0 | ||||
self._cond.notify_all() | ||||
def abort(self): | ||||
"""Place the barrier into a 'broken' state. | ||||
Useful in case of error. Any currently waiting threads and threads | ||||
attempting to 'wait()' will have BrokenBarrierError raised. | ||||
""" | ||||
with self._cond: | ||||
self._break() | ||||
def _break(self): | ||||
# An internal error was detected. The barrier is set to | ||||
# a broken state all parties awakened. | ||||
self._state = -2 | ||||
self._cond.notify_all() | ||||
@property | ||||
def parties(self): | ||||
"""Return the number of threads required to trip the barrier.""" | ||||
return self._parties | ||||
@property | ||||
def n_waiting(self): | ||||
"""Return the number of threads currently waiting at the barrier.""" | ||||
# We don't need synchronization here since this is an ephemeral result | ||||
# anyway. It returns the correct value in the steady state. | ||||
if self._state == 0: | ||||
return self._count | ||||
return 0 | ||||
@property | ||||
def broken(self): | ||||
"""Return True if the barrier is in a broken state.""" | ||||
return self._state == -2 | ||||
# exception raised by the Barrier class | ||||
class BrokenBarrierError(RuntimeError): | ||||
pass | ||||
# Helper to generate new thread names | ||||
_counter = 0 | ||||
def _newname(template="Thread-%d"): | ||||
global _counter | ||||
_counter = _counter + 1 | ||||
return template % _counter | ||||
# Active thread administration | ||||
_active_limbo_lock = _allocate_lock() | ||||
_active = {} # maps thread id to Thread object | ||||
_limbo = {} | ||||
# For debug and leak testing | ||||
_dangling = WeakSet() | ||||
# Main class for threads | ||||
class Thread: | ||||
"""A class that represents a thread of control. | ||||
This class can be safely subclassed in a limited fashion. There are two ways | ||||
to specify the activity: by passing a callable object to the constructor, or | ||||
by overriding the run() method in a subclass. | ||||
""" | ||||
__initialized = False | ||||
# Need to store a reference to sys.exc_info for printing | ||||
# out exceptions when a thread tries to use a global var. during interp. | ||||
# shutdown and thus raises an exception about trying to perform some | ||||
# operation on/with a NoneType | ||||
__exc_info = _sys.exc_info | ||||
# Keep sys.exc_clear too to clear the exception just before | ||||
# allowing .join() to return. | ||||
#XXX __exc_clear = _sys.exc_clear | ||||
def __init__(self, group=None, target=None, name=None, | ||||
args=(), kwargs=None, *, daemon=None): | ||||
"""This constructor should always be called with keyword arguments. Arguments are: | ||||
*group* should be None; reserved for future extension when a ThreadGroup | ||||
class is implemented. | ||||
*target* is the callable object to be invoked by the run() | ||||
method. Defaults to None, meaning nothing is called. | ||||
*name* is the thread name. By default, a unique name is constructed of | ||||
the form "Thread-N" where N is a small decimal number. | ||||
*args* is the argument tuple for the target invocation. Defaults to (). | ||||
*kwargs* is a dictionary of keyword arguments for the target | ||||
invocation. Defaults to {}. | ||||
If a subclass overrides the constructor, it must make sure to invoke | ||||
the base class constructor (Thread.__init__()) before doing anything | ||||
else to the thread. | ||||
""" | ||||
assert group is None, "group argument must be None for now" | ||||
if kwargs is None: | ||||
kwargs = {} | ||||
self._target = target | ||||
self._name = str(name or _newname()) | ||||
self._args = args | ||||
self._kwargs = kwargs | ||||
if daemon is not None: | ||||
self._daemonic = daemon | ||||
else: | ||||
self._daemonic = current_thread().daemon | ||||
self._ident = None | ||||
self._started = Event() | ||||
self._stopped = False | ||||
self._block = Condition(Lock()) | ||||
self._initialized = True | ||||
# sys.stderr is not stored in the class like | ||||
# sys.exc_info since it can be changed between instances | ||||
self._stderr = _sys.stderr | ||||
_dangling.add(self) | ||||
def _reset_internal_locks(self): | ||||
# private! Called by _after_fork() to reset our internal locks as | ||||
# they may be in an invalid state leading to a deadlock or crash. | ||||
if hasattr(self, '_block'): # DummyThread deletes _block | ||||
self._block.__init__() | ||||
self._started._reset_internal_locks() | ||||
def __repr__(self): | ||||
assert self._initialized, "Thread.__init__() was not called" | ||||
status = "initial" | ||||
if self._started.is_set(): | ||||
status = "started" | ||||
if self._stopped: | ||||
status = "stopped" | ||||
if self._daemonic: | ||||
status += " daemon" | ||||
if self._ident is not None: | ||||
status += " %s" % self._ident | ||||
return "<%s(%s, %s)>" % (self.__class__.__name__, self._name, status) | ||||
def start(self): | ||||
"""Start the thread's activity. | ||||
It must be called at most once per thread object. It arranges for the | ||||
object's run() method to be invoked in a separate thread of control. | ||||
This method will raise a RuntimeError if called more than once on the | ||||
same thread object. | ||||
""" | ||||
if not self._initialized: | ||||
raise RuntimeError("thread.__init__() not called") | ||||
if self._started.is_set(): | ||||
raise RuntimeError("threads can only be started once") | ||||
with _active_limbo_lock: | ||||
_limbo[self] = self | ||||
try: | ||||
_start_new_thread(self._bootstrap, ()) | ||||
except Exception: | ||||
with _active_limbo_lock: | ||||
del _limbo[self] | ||||
raise | ||||
self._started.wait() | ||||
def run(self): | ||||
"""Method representing the thread's activity. | ||||
You may override this method in a subclass. The standard run() method | ||||
invokes the callable object passed to the object's constructor as the | ||||
target argument, if any, with sequential and keyword arguments taken | ||||
from the args and kwargs arguments, respectively. | ||||
""" | ||||
try: | ||||
if self._target: | ||||
self._target(*self._args, **self._kwargs) | ||||
finally: | ||||
# Avoid a refcycle if the thread is running a function with | ||||
# an argument that has a member that points to the thread. | ||||
del self._target, self._args, self._kwargs | ||||
def _bootstrap(self): | ||||
# Wrapper around the real bootstrap code that ignores | ||||
# exceptions during interpreter cleanup. Those typically | ||||
# happen when a daemon thread wakes up at an unfortunate | ||||
# moment, finds the world around it destroyed, and raises some | ||||
# random exception *** while trying to report the exception in | ||||
# _bootstrap_inner() below ***. Those random exceptions | ||||
# don't help anybody, and they confuse users, so we suppress | ||||
# them. We suppress them only when it appears that the world | ||||
# indeed has already been destroyed, so that exceptions in | ||||
# _bootstrap_inner() during normal business hours are properly | ||||
# reported. Also, we only suppress them for daemonic threads; | ||||
# if a non-daemonic encounters this, something else is wrong. | ||||
try: | ||||
self._bootstrap_inner() | ||||
except: | ||||
if self._daemonic and _sys is None: | ||||
return | ||||
raise | ||||
def _set_ident(self): | ||||
self._ident = get_ident() | ||||
def _bootstrap_inner(self): | ||||
try: | ||||
self._set_ident() | ||||
self._started.set() | ||||
with _active_limbo_lock: | ||||
_active[self._ident] = self | ||||
del _limbo[self] | ||||
if _trace_hook: | ||||
_sys.settrace(_trace_hook) | ||||
if _profile_hook: | ||||
_sys.setprofile(_profile_hook) | ||||
try: | ||||
self.run() | ||||
except SystemExit: | ||||
pass | ||||
except: | ||||
# If sys.stderr is no more (most likely from interpreter | ||||
# shutdown) use self._stderr. Otherwise still use sys (as in | ||||
# _sys) in case sys.stderr was redefined since the creation of | ||||
# self. | ||||
if _sys: | ||||
_sys.stderr.write("Exception in thread %s:\n%s\n" % | ||||
(self.name, _format_exc())) | ||||
else: | ||||
# Do the best job possible w/o a huge amt. of code to | ||||
# approximate a traceback (code ideas from | ||||
# Lib/traceback.py) | ||||
exc_type, exc_value, exc_tb = self._exc_info() | ||||
try: | ||||
print(( | ||||
"Exception in thread " + self.name + | ||||
" (most likely raised during interpreter shutdown):"), file=self._stderr) | ||||
print(( | ||||
"Traceback (most recent call last):"), file=self._stderr) | ||||
while exc_tb: | ||||
print(( | ||||
' File "%s", line %s, in %s' % | ||||
(exc_tb.tb_frame.f_code.co_filename, | ||||
exc_tb.tb_lineno, | ||||
exc_tb.tb_frame.f_code.co_name)), file=self._stderr) | ||||
exc_tb = exc_tb.tb_next | ||||
print(("%s: %s" % (exc_type, exc_value)), file=self._stderr) | ||||
# Make sure that exc_tb gets deleted since it is a memory | ||||
# hog; deleting everything else is just for thoroughness | ||||
finally: | ||||
del exc_type, exc_value, exc_tb | ||||
finally: | ||||
# Prevent a race in | ||||
# test_threading.test_no_refcycle_through_target when | ||||
# the exception keeps the target alive past when we | ||||
# assert that it's dead. | ||||
#XXX self.__exc_clear() | ||||
pass | ||||
finally: | ||||
with _active_limbo_lock: | ||||
self._stop() | ||||
try: | ||||
# We don't call self._delete() because it also | ||||
# grabs _active_limbo_lock. | ||||
del _active[get_ident()] | ||||
except: | ||||
pass | ||||
def _stop(self): | ||||
self._block.acquire() | ||||
self._stopped = True | ||||
self._block.notify_all() | ||||
self._block.release() | ||||
def _delete(self): | ||||
"Remove current thread from the dict of currently running threads." | ||||
# Notes about running with _dummy_thread: | ||||
# | ||||
# Must take care to not raise an exception if _dummy_thread is being | ||||
# used (and thus this module is being used as an instance of | ||||
# dummy_threading). _dummy_thread.get_ident() always returns -1 since | ||||
# there is only one thread if _dummy_thread is being used. Thus | ||||
# len(_active) is always <= 1 here, and any Thread instance created | ||||
# overwrites the (if any) thread currently registered in _active. | ||||
# | ||||
# An instance of _MainThread is always created by 'threading'. This | ||||
# gets overwritten the instant an instance of Thread is created; both | ||||
# threads return -1 from _dummy_thread.get_ident() and thus have the | ||||
# same key in the dict. So when the _MainThread instance created by | ||||
# 'threading' tries to clean itself up when atexit calls this method | ||||
# it gets a KeyError if another Thread instance was created. | ||||
# | ||||
# This all means that KeyError from trying to delete something from | ||||
# _active if dummy_threading is being used is a red herring. But | ||||
# since it isn't if dummy_threading is *not* being used then don't | ||||
# hide the exception. | ||||
try: | ||||
with _active_limbo_lock: | ||||
del _active[get_ident()] | ||||
# There must not be any python code between the previous line | ||||
# and after the lock is released. Otherwise a tracing function | ||||
# could try to acquire the lock again in the same thread, (in | ||||
# current_thread()), and would block. | ||||
except KeyError: | ||||
if 'dummy_threading' not in _sys.modules: | ||||
raise | ||||
def join(self, timeout=None): | ||||
"""Wait until the thread terminates. | ||||
This blocks the calling thread until the thread whose join() method is | ||||
called terminates -- either normally or through an unhandled exception | ||||
or until the optional timeout occurs. | ||||
When the timeout argument is present and not None, it should be a | ||||
floating point number specifying a timeout for the operation in seconds | ||||
(or fractions thereof). As join() always returns None, you must call | ||||
isAlive() after join() to decide whether a timeout happened -- if the | ||||
thread is still alive, the join() call timed out. | ||||
When the timeout argument is not present or None, the operation will | ||||
block until the thread terminates. | ||||
A thread can be join()ed many times. | ||||
join() raises a RuntimeError if an attempt is made to join the current | ||||
thread as that would cause a deadlock. It is also an error to join() a | ||||
thread before it has been started and attempts to do so raises the same | ||||
exception. | ||||
""" | ||||
if not self._initialized: | ||||
raise RuntimeError("Thread.__init__() not called") | ||||
if not self._started.is_set(): | ||||
raise RuntimeError("cannot join thread before it is started") | ||||
if self is current_thread(): | ||||
raise RuntimeError("cannot join current thread") | ||||
self._block.acquire() | ||||
try: | ||||
if timeout is None: | ||||
while not self._stopped: | ||||
self._block.wait() | ||||
else: | ||||
deadline = _time() + timeout | ||||
while not self._stopped: | ||||
delay = deadline - _time() | ||||
if delay <= 0: | ||||
break | ||||
self._block.wait(delay) | ||||
finally: | ||||
self._block.release() | ||||
@property | ||||
def name(self): | ||||
"""A string used for identification purposes only. | ||||
It has no semantics. Multiple threads may be given the same name. The | ||||
initial name is set by the constructor. | ||||
""" | ||||
assert self._initialized, "Thread.__init__() not called" | ||||
return self._name | ||||
@name.setter | ||||
def name(self, name): | ||||
assert self._initialized, "Thread.__init__() not called" | ||||
self._name = str(name) | ||||
@property | ||||
def ident(self): | ||||
"""Thread identifier of this thread or None if it has not been started. | ||||
This is a nonzero integer. See the thread.get_ident() function. Thread | ||||
identifiers may be recycled when a thread exits and another thread is | ||||
created. The identifier is available even after the thread has exited. | ||||
""" | ||||
assert self._initialized, "Thread.__init__() not called" | ||||
return self._ident | ||||
def is_alive(self): | ||||
"""Return whether the thread is alive. | ||||
This method returns True just before the run() method starts until just | ||||
after the run() method terminates. The module function enumerate() | ||||
returns a list of all alive threads. | ||||
""" | ||||
assert self._initialized, "Thread.__init__() not called" | ||||
return self._started.is_set() and not self._stopped | ||||
isAlive = is_alive | ||||
@property | ||||
def daemon(self): | ||||
"""A boolean value indicating whether this thread is a daemon thread. | ||||
This must be set before start() is called, otherwise RuntimeError is | ||||
raised. Its initial value is inherited from the creating thread; the | ||||
main thread is not a daemon thread and therefore all threads created in | ||||
the main thread default to daemon = False. | ||||
The entire Python program exits when no alive non-daemon threads are | ||||
left. | ||||
""" | ||||
assert self._initialized, "Thread.__init__() not called" | ||||
return self._daemonic | ||||
@daemon.setter | ||||
def daemon(self, daemonic): | ||||
if not self._initialized: | ||||
raise RuntimeError("Thread.__init__() not called") | ||||
if self._started.is_set(): | ||||
raise RuntimeError("cannot set daemon status of active thread"); | ||||
self._daemonic = daemonic | ||||
def isDaemon(self): | ||||
return self.daemon | ||||
def setDaemon(self, daemonic): | ||||
self.daemon = daemonic | ||||
def getName(self): | ||||
return self.name | ||||
def setName(self, name): | ||||
self.name = name | ||||
# The timer class was contributed by Itamar Shtull-Trauring | ||||
class Timer(Thread): | ||||
"""Call a function after a specified number of seconds: | ||||
t = Timer(30.0, f, args=None, kwargs=None) | ||||
t.start() | ||||
t.cancel() # stop the timer's action if it's still waiting | ||||
""" | ||||
def __init__(self, interval, function, args=None, kwargs=None): | ||||
Thread.__init__(self) | ||||
self.interval = interval | ||||
self.function = function | ||||
self.args = args if args is not None else [] | ||||
self.kwargs = kwargs if kwargs is not None else {} | ||||
self.finished = Event() | ||||
def cancel(self): | ||||
"""Stop the timer if it hasn't finished yet.""" | ||||
self.finished.set() | ||||
def run(self): | ||||
self.finished.wait(self.interval) | ||||
if not self.finished.is_set(): | ||||
self.function(*self.args, **self.kwargs) | ||||
self.finished.set() | ||||
# Special thread class to represent the main thread | ||||
# This is garbage collected through an exit handler | ||||
class _MainThread(Thread): | ||||
def __init__(self): | ||||
Thread.__init__(self, name="MainThread", daemon=False) | ||||
self._started.set() | ||||
self._set_ident() | ||||
with _active_limbo_lock: | ||||
_active[self._ident] = self | ||||
def _exitfunc(self): | ||||
self._stop() | ||||
t = _pickSomeNonDaemonThread() | ||||
while t: | ||||
t.join() | ||||
t = _pickSomeNonDaemonThread() | ||||
self._delete() | ||||
def _pickSomeNonDaemonThread(): | ||||
for t in enumerate(): | ||||
if not t.daemon and t.is_alive(): | ||||
return t | ||||
return None | ||||
# Dummy thread class to represent threads not started here. | ||||
# These aren't garbage collected when they die, nor can they be waited for. | ||||
# If they invoke anything in threading.py that calls current_thread(), they | ||||
# leave an entry in the _active dict forever after. | ||||
# Their purpose is to return *something* from current_thread(). | ||||
# They are marked as daemon threads so we won't wait for them | ||||
# when we exit (conform previous semantics). | ||||
class _DummyThread(Thread): | ||||
def __init__(self): | ||||
Thread.__init__(self, name=_newname("Dummy-%d"), daemon=True) | ||||
# Thread._block consumes an OS-level locking primitive, which | ||||
# can never be used by a _DummyThread. Since a _DummyThread | ||||
# instance is immortal, that's bad, so release this resource. | ||||
del self._block | ||||
self._started.set() | ||||
self._set_ident() | ||||
with _active_limbo_lock: | ||||
_active[self._ident] = self | ||||
def _stop(self): | ||||
pass | ||||
def join(self, timeout=None): | ||||
assert False, "cannot join a dummy thread" | ||||
# Global API functions | ||||
def current_thread(): | ||||
"""Return the current Thread object, corresponding to the caller's thread of control. | ||||
If the caller's thread of control was not created through the threading | ||||
module, a dummy thread object with limited functionality is returned. | ||||
""" | ||||
try: | ||||
return _active[get_ident()] | ||||
except KeyError: | ||||
return _DummyThread() | ||||
currentThread = current_thread | ||||
def active_count(): | ||||
"""Return the number of Thread objects currently alive. | ||||
The returned count is equal to the length of the list returned by | ||||
enumerate(). | ||||
""" | ||||
with _active_limbo_lock: | ||||
return len(_active) + len(_limbo) | ||||
activeCount = active_count | ||||
def _enumerate(): | ||||
# Same as enumerate(), but without the lock. Internal use only. | ||||
return list(_active.values()) + list(_limbo.values()) | ||||
def enumerate(): | ||||
"""Return a list of all Thread objects currently alive. | ||||
The list includes daemonic threads, dummy thread objects created by | ||||
current_thread(), and the main thread. It excludes terminated threads and | ||||
threads that have not yet been started. | ||||
""" | ||||
with _active_limbo_lock: | ||||
return list(_active.values()) + list(_limbo.values()) | ||||
from _thread import stack_size | ||||
# Create the main thread object, | ||||
# and make it available for the interpreter | ||||
# (Py_Main) as threading._shutdown. | ||||
_shutdown = _MainThread()._exitfunc | ||||
# get thread-local implementation, either from the thread | ||||
# module, or from the python fallback | ||||
try: | ||||
from _thread import _local as local | ||||
except ImportError: | ||||
from _threading_local import local | ||||
def _after_fork(): | ||||
# This function is called by Python/ceval.c:PyEval_ReInitThreads which | ||||
# is called from PyOS_AfterFork. Here we cleanup threading module state | ||||
# that should not exist after a fork. | ||||
# Reset _active_limbo_lock, in case we forked while the lock was held | ||||
# by another (non-forked) thread. http://bugs.python.org/issue874900 | ||||
global _active_limbo_lock | ||||
_active_limbo_lock = _allocate_lock() | ||||
# fork() only copied the current thread; clear references to others. | ||||
new_active = {} | ||||
current = current_thread() | ||||
with _active_limbo_lock: | ||||
for thread in _enumerate(): | ||||
# Any lock/condition variable may be currently locked or in an | ||||
# invalid state, so we reinitialize them. | ||||
thread._reset_internal_locks() | ||||
if thread is current: | ||||
# There is only one active thread. We reset the ident to | ||||
# its new value since it can have changed. | ||||
ident = get_ident() | ||||
thread._ident = ident | ||||
new_active[ident] = thread | ||||
else: | ||||
# All the others are already stopped. | ||||
thread._stop() | ||||
_limbo.clear() | ||||
_active.clear() | ||||
_active.update(new_active) | ||||
assert len(_active) == 1 | ||||