Commit 2a12974b authored by Victor Stinner's avatar Victor Stinner

Close #12028: Make threading._get_ident() public, rename it to

threading.get_ident() and document it. This function was used by
_thread.get_ident().
parent d976098e
...@@ -187,10 +187,9 @@ The :mod:`signal` module defines the following functions: ...@@ -187,10 +187,9 @@ The :mod:`signal` module defines the following functions:
Send the signal *signum* to the thread *thread_id*, another thread in the same Send the signal *signum* to the thread *thread_id*, another thread in the same
process as the caller. The signal is asynchronously directed to thread. process as the caller. The signal is asynchronously directed to thread.
*thread_id* can be read from the :attr:`~threading.Thread.ident` attribute Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident`
of :attr:`threading.Thread`. For example, attribute of :attr:`threading.Thread` to get a 'thread identifier' for
``threading.current_thread().ident`` gives the identifier of the current *thread_id*.
thread.
If *signum* is 0, then no signal is sent, but error checking is still If *signum* is 0, then no signal is sent, but error checking is still
performed; this can be used to check if a thread is still running. performed; this can be used to check if a thread is still running.
......
...@@ -48,6 +48,17 @@ This module defines the following functions and objects: ...@@ -48,6 +48,17 @@ This module defines the following functions and objects:
returned. returned.
.. function:: get_ident()
Return the 'thread identifier' of the current thread. This is a nonzero
integer. Its value has no direct meaning; it is intended as a magic cookie
to be used e.g. to index a dictionary of thread-specific data. Thread
identifiers may be recycled when a thread exits and another thread is
created.
.. versionadded:: 3.3
.. function:: enumerate() .. function:: enumerate()
Return a list of all :class:`Thread` objects currently alive. The list Return a list of all :class:`Thread` objects currently alive. The list
...@@ -332,10 +343,10 @@ impossible to detect the termination of alien threads. ...@@ -332,10 +343,10 @@ impossible to detect the termination of alien threads.
.. attribute:: ident .. attribute:: ident
The 'thread identifier' of this thread or ``None`` if the thread has not The 'thread identifier' of this thread or ``None`` if the thread has not
been started. This is a nonzero integer. See the been started. This is a nonzero integer. See the :func:`get_ident()`
:func:`thread.get_ident()` function. Thread identifiers may be recycled function. Thread identifiers may be recycled when a thread exits and
when a thread exits and another thread is created. The identifier is another thread is created. The identifier is available even after the
available even after the thread has exited. thread has exited.
.. method:: is_alive() .. method:: is_alive()
......
...@@ -41,10 +41,9 @@ except ImportError: #pragma: no cover ...@@ -41,10 +41,9 @@ except ImportError: #pragma: no cover
codecs = None codecs = None
try: try:
import _thread as thread
import threading import threading
except ImportError: #pragma: no cover except ImportError: #pragma: no cover
thread = None threading = None
__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
__status__ = "production" __status__ = "production"
...@@ -199,7 +198,7 @@ def _checkLevel(level): ...@@ -199,7 +198,7 @@ def _checkLevel(level):
#the lock would already have been acquired - so we need an RLock. #the lock would already have been acquired - so we need an RLock.
#The same argument applies to Loggers and Manager.loggerDict. #The same argument applies to Loggers and Manager.loggerDict.
# #
if thread: if threading:
_lock = threading.RLock() _lock = threading.RLock()
else: #pragma: no cover else: #pragma: no cover
_lock = None _lock = None
...@@ -278,8 +277,8 @@ class LogRecord(object): ...@@ -278,8 +277,8 @@ class LogRecord(object):
self.created = ct self.created = ct
self.msecs = (ct - int(ct)) * 1000 self.msecs = (ct - int(ct)) * 1000
self.relativeCreated = (self.created - _startTime) * 1000 self.relativeCreated = (self.created - _startTime) * 1000
if logThreads and thread: if logThreads and threading:
self.thread = thread.get_ident() self.thread = threading.get_ident()
self.threadName = threading.current_thread().name self.threadName = threading.current_thread().name
else: # pragma: no cover else: # pragma: no cover
self.thread = None self.thread = None
...@@ -773,7 +772,7 @@ class Handler(Filterer): ...@@ -773,7 +772,7 @@ class Handler(Filterer):
""" """
Acquire a thread lock for serializing access to the underlying I/O. Acquire a thread lock for serializing access to the underlying I/O.
""" """
if thread: if threading:
self.lock = threading.RLock() self.lock = threading.RLock()
else: #pragma: no cover else: #pragma: no cover
self.lock = None self.lock = None
......
...@@ -5,7 +5,7 @@ __all__ = ["Repr", "repr", "recursive_repr"] ...@@ -5,7 +5,7 @@ __all__ = ["Repr", "repr", "recursive_repr"]
import builtins import builtins
from itertools import islice from itertools import islice
try: try:
from _thread import get_ident from threading import get_ident
except ImportError: except ImportError:
from _dummy_thread import get_ident from _dummy_thread import get_ident
......
...@@ -4,7 +4,7 @@ Various tests for synchronization primitives. ...@@ -4,7 +4,7 @@ Various tests for synchronization primitives.
import sys import sys
import time import time
from _thread import start_new_thread, get_ident, TIMEOUT_MAX from _thread import start_new_thread, TIMEOUT_MAX
import threading import threading
import unittest import unittest
...@@ -31,7 +31,7 @@ class Bunch(object): ...@@ -31,7 +31,7 @@ class Bunch(object):
self.finished = [] self.finished = []
self._can_exit = not wait_before_exit self._can_exit = not wait_before_exit
def task(): def task():
tid = get_ident() tid = threading.get_ident()
self.started.append(tid) self.started.append(tid)
try: try:
f() f()
......
...@@ -190,18 +190,17 @@ def test_main(): ...@@ -190,18 +190,17 @@ def test_main():
idents = [] idents = []
def callback(): def callback():
idents.append(_thread.get_ident()) idents.append(threading.get_ident())
_testcapi._test_thread_state(callback) _testcapi._test_thread_state(callback)
a = b = callback a = b = callback
time.sleep(1) time.sleep(1)
# Check our main thread is in the list exactly 3 times. # Check our main thread is in the list exactly 3 times.
if idents.count(_thread.get_ident()) != 3: if idents.count(threading.get_ident()) != 3:
raise support.TestFailed( raise support.TestFailed(
"Couldn't find main thread correctly in the list") "Couldn't find main thread correctly in the list")
if threading: if threading:
import _thread
import time import time
TestThreadState() TestThreadState()
t = threading.Thread(target=TestThreadState) t = threading.Thread(target=TestThreadState)
......
...@@ -557,7 +557,7 @@ class PendingSignalsTests(unittest.TestCase): ...@@ -557,7 +557,7 @@ class PendingSignalsTests(unittest.TestCase):
def kill(self, signum): def kill(self, signum):
if self.has_pthread_kill: if self.has_pthread_kill:
tid = threading.current_thread().ident tid = threading.get_ident()
signal.pthread_kill(tid, signum) signal.pthread_kill(tid, signum)
else: else:
pid = os.getpid() pid = os.getpid()
...@@ -589,7 +589,7 @@ class PendingSignalsTests(unittest.TestCase): ...@@ -589,7 +589,7 @@ class PendingSignalsTests(unittest.TestCase):
'need signal.pthread_kill()') 'need signal.pthread_kill()')
def test_pthread_kill(self): def test_pthread_kill(self):
signum = signal.SIGUSR1 signum = signal.SIGUSR1
current = threading.current_thread().ident current = threading.get_ident()
old_handler = signal.signal(signum, self.handler) old_handler = signal.signal(signum, self.handler)
self.addCleanup(signal.signal, signum, old_handler) self.addCleanup(signal.signal, signum, old_handler)
......
...@@ -343,7 +343,7 @@ class SysModuleTest(unittest.TestCase): ...@@ -343,7 +343,7 @@ class SysModuleTest(unittest.TestCase):
# Test sys._current_frames() in a WITH_THREADS build. # Test sys._current_frames() in a WITH_THREADS build.
@test.support.reap_threads @test.support.reap_threads
def current_frames_with_threads(self): def current_frames_with_threads(self):
import threading, _thread import threading
import traceback import traceback
# Spawn a thread that blocks at a known place. Then the main # Spawn a thread that blocks at a known place. Then the main
...@@ -357,7 +357,7 @@ class SysModuleTest(unittest.TestCase): ...@@ -357,7 +357,7 @@ class SysModuleTest(unittest.TestCase):
g456() g456()
def g456(): def g456():
thread_info.append(_thread.get_ident()) thread_info.append(threading.get_ident())
entered_g.set() entered_g.set()
leave_g.wait() leave_g.wait()
...@@ -373,7 +373,7 @@ class SysModuleTest(unittest.TestCase): ...@@ -373,7 +373,7 @@ class SysModuleTest(unittest.TestCase):
d = sys._current_frames() d = sys._current_frames()
main_id = _thread.get_ident() main_id = threading.get_ident()
self.assertIn(main_id, d) self.assertIn(main_id, d)
self.assertIn(thread_id, d) self.assertIn(thread_id, d)
......
...@@ -30,7 +30,7 @@ def task(N, done, done_tasks, errors): ...@@ -30,7 +30,7 @@ def task(N, done, done_tasks, errors):
except Exception as e: except Exception as e:
errors.append(e.with_traceback(None)) errors.append(e.with_traceback(None))
finally: finally:
done_tasks.append(thread.get_ident()) done_tasks.append(threading.get_ident())
finished = len(done_tasks) == N finished = len(done_tasks) == N
if finished: if finished:
done.set() done.set()
......
...@@ -173,7 +173,7 @@ class ThreadTests(BaseTestCase): ...@@ -173,7 +173,7 @@ class ThreadTests(BaseTestCase):
exception = ctypes.py_object(AsyncExc) exception = ctypes.py_object(AsyncExc)
# First check it works when setting the exception from the same thread. # First check it works when setting the exception from the same thread.
tid = _thread.get_ident() tid = threading.get_ident()
try: try:
result = set_async_exc(ctypes.c_long(tid), exception) result = set_async_exc(ctypes.c_long(tid), exception)
...@@ -202,7 +202,7 @@ class ThreadTests(BaseTestCase): ...@@ -202,7 +202,7 @@ class ThreadTests(BaseTestCase):
class Worker(threading.Thread): class Worker(threading.Thread):
def run(self): def run(self):
self.id = _thread.get_ident() self.id = threading.get_ident()
self.finished = False self.finished = False
try: try:
......
...@@ -24,7 +24,7 @@ __all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event', ...@@ -24,7 +24,7 @@ __all__ = ['active_count', 'Condition', 'current_thread', 'enumerate', 'Event',
# Rename some stuff so "from threading import *" is safe # Rename some stuff so "from threading import *" is safe
_start_new_thread = _thread.start_new_thread _start_new_thread = _thread.start_new_thread
_allocate_lock = _thread.allocate_lock _allocate_lock = _thread.allocate_lock
_get_ident = _thread.get_ident get_ident = _thread.get_ident
ThreadError = _thread.error ThreadError = _thread.error
try: try:
_CRLock = _thread.RLock _CRLock = _thread.RLock
...@@ -52,7 +52,7 @@ if __debug__: ...@@ -52,7 +52,7 @@ if __debug__:
format = format % args format = format % args
# Issue #4188: calling current_thread() can incur an infinite # Issue #4188: calling current_thread() can incur an infinite
# recursion if it has to create a DummyThread on the fly. # recursion if it has to create a DummyThread on the fly.
ident = _get_ident() ident = get_ident()
try: try:
name = _active[ident].name name = _active[ident].name
except KeyError: except KeyError:
...@@ -110,7 +110,7 @@ class _RLock(_Verbose): ...@@ -110,7 +110,7 @@ class _RLock(_Verbose):
self.__class__.__name__, owner, self._count) self.__class__.__name__, owner, self._count)
def acquire(self, blocking=True, timeout=-1): def acquire(self, blocking=True, timeout=-1):
me = _get_ident() me = get_ident()
if self._owner == me: if self._owner == me:
self._count = self._count + 1 self._count = self._count + 1
if __debug__: if __debug__:
...@@ -130,7 +130,7 @@ class _RLock(_Verbose): ...@@ -130,7 +130,7 @@ class _RLock(_Verbose):
__enter__ = acquire __enter__ = acquire
def release(self): def release(self):
if self._owner != _get_ident(): if self._owner != get_ident():
raise RuntimeError("cannot release un-acquired lock") raise RuntimeError("cannot release un-acquired lock")
self._count = count = self._count - 1 self._count = count = self._count - 1
if not count: if not count:
...@@ -166,7 +166,7 @@ class _RLock(_Verbose): ...@@ -166,7 +166,7 @@ class _RLock(_Verbose):
return (count, owner) return (count, owner)
def _is_owned(self): def _is_owned(self):
return self._owner == _get_ident() return self._owner == get_ident()
_PyRLock = _RLock _PyRLock = _RLock
...@@ -714,7 +714,7 @@ class Thread(_Verbose): ...@@ -714,7 +714,7 @@ class Thread(_Verbose):
raise raise
def _set_ident(self): def _set_ident(self):
self._ident = _get_ident() self._ident = get_ident()
def _bootstrap_inner(self): def _bootstrap_inner(self):
try: try:
...@@ -787,7 +787,7 @@ class Thread(_Verbose): ...@@ -787,7 +787,7 @@ class Thread(_Verbose):
try: try:
# We don't call self._delete() because it also # We don't call self._delete() because it also
# grabs _active_limbo_lock. # grabs _active_limbo_lock.
del _active[_get_ident()] del _active[get_ident()]
except: except:
pass pass
...@@ -823,7 +823,7 @@ class Thread(_Verbose): ...@@ -823,7 +823,7 @@ class Thread(_Verbose):
try: try:
with _active_limbo_lock: with _active_limbo_lock:
del _active[_get_ident()] del _active[get_ident()]
# There must not be any python code between the previous line # There must not be any python code between the previous line
# and after the lock is released. Otherwise a tracing function # and after the lock is released. Otherwise a tracing function
# could try to acquire the lock again in the same thread, (in # could try to acquire the lock again in the same thread, (in
...@@ -1006,9 +1006,8 @@ class _DummyThread(Thread): ...@@ -1006,9 +1006,8 @@ class _DummyThread(Thread):
def current_thread(): def current_thread():
try: try:
return _active[_get_ident()] return _active[get_ident()]
except KeyError: except KeyError:
##print "current_thread(): no current thread for", _get_ident()
return _DummyThread() return _DummyThread()
currentThread = current_thread currentThread = current_thread
...@@ -1062,7 +1061,7 @@ def _after_fork(): ...@@ -1062,7 +1061,7 @@ def _after_fork():
if thread is current: if thread is current:
# There is only one active thread. We reset the ident to # There is only one active thread. We reset the ident to
# its new value since it can have changed. # its new value since it can have changed.
ident = _get_ident() ident = get_ident()
thread._ident = ident thread._ident = ident
# Any condition variables hanging off of the active thread may # Any condition variables hanging off of the active thread may
# be in an invalid state, so we reinitialize them. # be in an invalid state, so we reinitialize them.
......
...@@ -177,6 +177,10 @@ Core and Builtins ...@@ -177,6 +177,10 @@ Core and Builtins
Library Library
------- -------
- Issue #12028: Make threading._get_ident() public, rename it to
threading.get_ident() and document it. This function was used by
_thread.get_ident().
- Issue #12171: IncrementalEncoder.reset() of CJK codecs (multibytecodec) calls - Issue #12171: IncrementalEncoder.reset() of CJK codecs (multibytecodec) calls
encreset() instead of decreset(). encreset() instead of decreset().
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment