From e8406df0c7f65212f9dc305daf4f0075e50ac665 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 25 Feb 2011 22:07:43 +0000 Subject: Issue #6064: Add a `daemon` keyword argument to the threading.Thread and multiprocessing.Process constructors in order to override the default behaviour of inheriting the daemonic property from the current thread/process. --- Lib/threading.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index fd93f74333..cb09afaa66 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -622,7 +622,7 @@ class Thread(_Verbose): #XXX __exc_clear = _sys.exc_clear def __init__(self, group=None, target=None, name=None, - args=(), kwargs=None, verbose=None): + args=(), kwargs=None, verbose=None, *, daemon=None): assert group is None, "group argument must be None for now" _Verbose.__init__(self, verbose) if kwargs is None: @@ -631,7 +631,10 @@ class Thread(_Verbose): self._name = str(name or _newname()) self._args = args self._kwargs = kwargs - self._daemonic = self._set_daemon() + if daemon is not None: + self._daemonic = daemon + else: + self._daemonic = current_thread().daemon self._ident = None self._started = Event() self._stopped = False @@ -648,10 +651,6 @@ class Thread(_Verbose): self._block.__init__() self._started._reset_internal_locks() - def _set_daemon(self): - # Overridden in _MainThread and _DummyThread - return current_thread().daemon - def __repr__(self): assert self._initialized, "Thread.__init__() was not called" status = "initial" @@ -948,15 +947,12 @@ class _Timer(Thread): class _MainThread(Thread): def __init__(self): - Thread.__init__(self, name="MainThread") + Thread.__init__(self, name="MainThread", daemon=False) self._started.set() self._set_ident() with _active_limbo_lock: _active[self._ident] = self - def _set_daemon(self): - return False - def _exitfunc(self): self._stop() t = _pickSomeNonDaemonThread() @@ -988,7 +984,7 @@ def _pickSomeNonDaemonThread(): class _DummyThread(Thread): def __init__(self): - Thread.__init__(self, name=_newname("Dummy-%d")) + 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 @@ -1000,9 +996,6 @@ class _DummyThread(Thread): with _active_limbo_lock: _active[self._ident] = self - def _set_daemon(self): - return True - def join(self, timeout=None): assert False, "cannot join a dummy thread" -- cgit v1.2.1 From 87c4bc18d9591c89d76f68cbd67960d2a1309075 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 19 Apr 2011 23:58:51 +0200 Subject: Issue #11223: Add threading._info() function providing informations about the thread implementation. Skip test_lock_acquire_interruption() and test_rlock_acquire_interruption() of test_threadsignals if a thread lock is implemented using a POSIX mutex and a POSIX condition variable. A POSIX condition variable cannot be interrupted by a signal (e.g. on Linux, the futex system call is restarted). --- Lib/threading.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index cb09afaa66..eb3cb626c3 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -19,7 +19,7 @@ from collections import deque __all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier', - 'Timer', 'setprofile', 'settrace', 'local', 'stack_size'] + 'Timer', 'setprofile', 'settrace', 'local', 'stack_size', '_info'] # Rename some stuff so "from threading import *" is safe _start_new_thread = _thread.start_new_thread @@ -31,6 +31,7 @@ try: except AttributeError: _CRLock = None TIMEOUT_MAX = _thread.TIMEOUT_MAX +_info = _thread.info del _thread -- cgit v1.2.1 From 889c8e166a0ca7e819813348e79e900128ce100d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 24 Apr 2011 23:41:33 +0200 Subject: Issue #11915: threading.RLock()._release_save() raises a RuntimeError if the lock was not acquired. --- Lib/threading.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index eb3cb626c3..28c2146671 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -157,6 +157,8 @@ class _RLock(_Verbose): def _release_save(self): if __debug__: self._note("%s._release_save()", self) + if self._count == 0: + raise RuntimeError("cannot release un-acquired lock") count = self._count self._count = 0 owner = self._owner -- cgit v1.2.1 From da93e1034d0920de202f9ff0e941cc76dfc3e925 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 30 Apr 2011 14:53:09 +0200 Subject: Issue #11223: Replace threading._info() by sys.thread_info --- Lib/threading.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index 28c2146671..fafe7792f5 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -19,7 +19,7 @@ from collections import deque __all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier', - 'Timer', 'setprofile', 'settrace', 'local', 'stack_size', '_info'] + 'Timer', 'setprofile', 'settrace', 'local', 'stack_size'] # Rename some stuff so "from threading import *" is safe _start_new_thread = _thread.start_new_thread @@ -31,7 +31,6 @@ try: except AttributeError: _CRLock = None TIMEOUT_MAX = _thread.TIMEOUT_MAX -_info = _thread.info del _thread -- cgit v1.2.1 From 2ccd281bc2741b0fe14884c8d6ae1bf76bbb6847 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 30 May 2011 23:02:52 +0200 Subject: Close #12028: Make threading._get_ident() public, rename it to threading.get_ident() and document it. This function was used by _thread.get_ident(). --- Lib/threading.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index fafe7792f5..1f638b43c3 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -24,7 +24,7 @@ __all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event', # 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 +get_ident = _thread.get_ident ThreadError = _thread.error try: _CRLock = _thread.RLock @@ -52,7 +52,7 @@ if __debug__: format = format % args # Issue #4188: calling current_thread() can incur an infinite # recursion if it has to create a DummyThread on the fly. - ident = _get_ident() + ident = get_ident() try: name = _active[ident].name except KeyError: @@ -110,7 +110,7 @@ class _RLock(_Verbose): self.__class__.__name__, owner, self._count) def acquire(self, blocking=True, timeout=-1): - me = _get_ident() + me = get_ident() if self._owner == me: self._count = self._count + 1 if __debug__: @@ -130,7 +130,7 @@ class _RLock(_Verbose): __enter__ = acquire def release(self): - if self._owner != _get_ident(): + if self._owner != get_ident(): raise RuntimeError("cannot release un-acquired lock") self._count = count = self._count - 1 if not count: @@ -166,7 +166,7 @@ class _RLock(_Verbose): return (count, owner) def _is_owned(self): - return self._owner == _get_ident() + return self._owner == get_ident() _PyRLock = _RLock @@ -714,7 +714,7 @@ class Thread(_Verbose): raise def _set_ident(self): - self._ident = _get_ident() + self._ident = get_ident() def _bootstrap_inner(self): try: @@ -787,7 +787,7 @@ class Thread(_Verbose): try: # We don't call self._delete() because it also # grabs _active_limbo_lock. - del _active[_get_ident()] + del _active[get_ident()] except: pass @@ -823,7 +823,7 @@ class Thread(_Verbose): try: with _active_limbo_lock: - del _active[_get_ident()] + 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 @@ -1006,9 +1006,8 @@ class _DummyThread(Thread): def current_thread(): try: - return _active[_get_ident()] + return _active[get_ident()] except KeyError: - ##print "current_thread(): no current thread for", _get_ident() return _DummyThread() currentThread = current_thread @@ -1062,7 +1061,7 @@ def _after_fork(): 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() + ident = get_ident() thread._ident = ident # Any condition variables hanging off of the active thread may # be in an invalid state, so we reinitialize them. -- cgit v1.2.1 From 5ad70b684e0eac7852bfffe225be4731b4e6ac20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Thu, 28 Jul 2011 00:28:28 +0200 Subject: Remove indirection in threading (issue #10968). The public names (Thread, Condition, etc.) used to be factory functions returning instances of hidden classes (_Thread, _Condition, etc.), because (if Guido recalls correctly) this code pre-dates the ability to subclass extension types. It is now possible to inherit from Thread and other classes, without having to import the private underscored names like multiprocessing did. A doc update will follow: a patch is under discussion on the issue. --- Lib/threading.py | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index 9681f02fb1..222e5d992a 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -172,10 +172,7 @@ class _RLock(_Verbose): _PyRLock = _RLock -def Condition(*args, **kwargs): - return _Condition(*args, **kwargs) - -class _Condition(_Verbose): +class Condition(_Verbose): def __init__(self, lock=None, verbose=None): _Verbose.__init__(self, verbose) @@ -308,10 +305,7 @@ class _Condition(_Verbose): notifyAll = notify_all -def Semaphore(*args, **kwargs): - return _Semaphore(*args, **kwargs) - -class _Semaphore(_Verbose): +class Semaphore(_Verbose): # After Tim Peters' semaphore class, but not quite the same (no maximum) @@ -366,25 +360,19 @@ class _Semaphore(_Verbose): self.release() -def BoundedSemaphore(*args, **kwargs): - return _BoundedSemaphore(*args, **kwargs) - -class _BoundedSemaphore(_Semaphore): +class BoundedSemaphore(Semaphore): """Semaphore that checks that # releases is <= # acquires""" def __init__(self, value=1, verbose=None): - _Semaphore.__init__(self, value, verbose) + Semaphore.__init__(self, value, verbose) self._initial_value = value def release(self): if self._value >= self._initial_value: raise ValueError("Semaphore released too many times") - return _Semaphore.release(self) + return Semaphore.release(self) -def Event(*args, **kwargs): - return _Event(*args, **kwargs) - -class _Event(_Verbose): +class Event(_Verbose): # After Tim Peters' event class (without is_posted()) @@ -918,10 +906,7 @@ class Thread(_Verbose): # The timer class was contributed by Itamar Shtull-Trauring -def Timer(*args, **kwargs): - return _Timer(*args, **kwargs) - -class _Timer(Thread): +class Timer(Thread): """Call a function after a specified number of seconds: t = Timer(30.0, f, args=[], kwargs={}) -- cgit v1.2.1 From a186c2664232b53910c3c4ad5e509c4f3b3eb6f2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 2 Aug 2011 13:05:47 -0500 Subject: add ThreadError to threading.__all__ (closes #12679) --- Lib/threading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Lib/threading.py') diff --git a/Lib/threading.py b/Lib/threading.py index 222e5d992a..b6632327ce 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -20,7 +20,7 @@ from _weakrefset import WeakSet __all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Barrier', - 'Timer', 'setprofile', 'settrace', 'local', 'stack_size'] + 'Timer', 'ThreadError', 'setprofile', 'settrace', 'local', 'stack_size'] # Rename some stuff so "from threading import *" is safe _start_new_thread = _thread.start_new_thread -- cgit v1.2.1