Add _PyThreadState_UncheckedGet()

Issue #26154: Add a new private _PyThreadState_UncheckedGet() function which
gets the current thread state, but don't call Py_FatalError() if it is NULL.

Python 3.5.1 removed the _PyThreadState_Current symbol from the Python C API to
no more expose complex and private atomic types. Atomic types depends on the
compiler or can even depend on compiler options. The new function
_PyThreadState_UncheckedGet() allows to get the variable value without having
to care of the exact implementation of atomic types.

Changes:

* Replace direct usage of the _PyThreadState_Current variable with a call to
  _PyThreadState_UncheckedGet().
* In pystate.c, replace direct usage of the _PyThreadState_Current variable
  with the PyThreadState_GET() macro for readability.
* Document also PyThreadState_Get() in pystate.h
This commit is contained in:
Victor Stinner 2016-01-20 11:12:38 +01:00
parent aebb6d3682
commit bfd316e750
7 changed files with 42 additions and 26 deletions

View file

@ -3,6 +3,12 @@
#include "Python.h"
#ifndef Py_BUILD_CORE
/* ensure that PyThreadState_GET() is a macro, not an alias to
* PyThreadState_Get() */
# error "pystate.c must be compiled with Py_BUILD_CORE defined"
#endif
/* --------------------------------------------------------------------------
CAUTION
@ -423,7 +429,7 @@ tstate_delete_common(PyThreadState *tstate)
void
PyThreadState_Delete(PyThreadState *tstate)
{
if (tstate == (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current))
if (tstate == PyThreadState_GET())
Py_FatalError("PyThreadState_Delete: tstate is still current");
#ifdef WITH_THREAD
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
@ -437,8 +443,7 @@ PyThreadState_Delete(PyThreadState *tstate)
void
PyThreadState_DeleteCurrent()
{
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
&_PyThreadState_Current);
PyThreadState *tstate = PyThreadState_GET();
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
@ -488,11 +493,17 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate)
}
PyThreadState *
_PyThreadState_UncheckedGet(void)
{
return PyThreadState_GET();
}
PyThreadState *
PyThreadState_Get(void)
{
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
&_PyThreadState_Current);
PyThreadState *tstate = PyThreadState_GET();
if (tstate == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
@ -503,8 +514,7 @@ PyThreadState_Get(void)
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
&_PyThreadState_Current);
PyThreadState *oldts = PyThreadState_GET();
_Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
/* It should not be possible for more than one thread state
@ -535,8 +545,7 @@ PyThreadState_Swap(PyThreadState *newts)
PyObject *
PyThreadState_GetDict(void)
{
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
&_PyThreadState_Current);
PyThreadState *tstate = PyThreadState_GET();
if (tstate == NULL)
return NULL;
@ -682,7 +691,7 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
return tstate == (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current);
return tstate == PyThreadState_GET();
}
/* Internal initialization/finalization functions called by
@ -774,9 +783,7 @@ PyGILState_GetThisThreadState(void)
int
PyGILState_Check(void)
{
/* can't use PyThreadState_Get() since it will assert that it has the GIL */
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
&_PyThreadState_Current);
PyThreadState *tstate = PyThreadState_GET();
return tstate && (tstate == PyGILState_GetThisThreadState());
}