|
|
@ -11,7 +11,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include "common.h" |
|
|
|
#include "common.h" |
|
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_THREAD) && defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) |
|
|
|
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) |
|
|
|
# include "../gil.h" |
|
|
|
# include "../gil.h" |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
@ -64,65 +64,41 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass); |
|
|
|
|
|
|
|
|
|
|
|
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
|
|
|
|
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
|
|
|
|
// Thread Specific Storage (TSS) API.
|
|
|
|
// Thread Specific Storage (TSS) API.
|
|
|
|
#if PY_VERSION_HEX >= 0x03070000 |
|
|
|
|
|
|
|
// Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
|
|
|
|
// Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
|
|
|
|
// `Py_LIMITED_API` anyway.
|
|
|
|
// `Py_LIMITED_API` anyway.
|
|
|
|
# if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
#if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
# define PYBIND11_TLS_KEY_REF Py_tss_t & |
|
|
|
# define PYBIND11_TLS_KEY_REF Py_tss_t & |
|
|
|
# if defined(__clang__) |
|
|
|
# if defined(__clang__) |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) \ |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) \ |
|
|
|
_Pragma("clang diagnostic push") /**/ \ |
|
|
|
_Pragma("clang diagnostic push") /**/ \ |
|
|
|
_Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \ |
|
|
|
_Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \ |
|
|
|
Py_tss_t var \ |
|
|
|
Py_tss_t var \ |
|
|
|
= Py_tss_NEEDS_INIT; \ |
|
|
|
= Py_tss_NEEDS_INIT; \ |
|
|
|
_Pragma("clang diagnostic pop") |
|
|
|
_Pragma("clang diagnostic pop") |
|
|
|
# elif defined(__GNUC__) && !defined(__INTEL_COMPILER) |
|
|
|
# elif defined(__GNUC__) && !defined(__INTEL_COMPILER) |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) \ |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) \ |
|
|
|
_Pragma("GCC diagnostic push") /**/ \ |
|
|
|
_Pragma("GCC diagnostic push") /**/ \ |
|
|
|
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \ |
|
|
|
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \ |
|
|
|
Py_tss_t var \ |
|
|
|
Py_tss_t var \ |
|
|
|
= Py_tss_NEEDS_INIT; \ |
|
|
|
= Py_tss_NEEDS_INIT; \ |
|
|
|
_Pragma("GCC diagnostic pop") |
|
|
|
_Pragma("GCC diagnostic pop") |
|
|
|
# else |
|
|
|
|
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT; |
|
|
|
|
|
|
|
# endif |
|
|
|
|
|
|
|
# define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key)) |
|
|
|
|
|
|
|
# else |
|
|
|
# else |
|
|
|
# define PYBIND11_TLS_KEY_REF Py_tss_t * |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT; |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr; |
|
|
|
|
|
|
|
# define PYBIND11_TLS_KEY_CREATE(var) \ |
|
|
|
|
|
|
|
(((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key) |
|
|
|
|
|
|
|
# endif |
|
|
|
# endif |
|
|
|
|
|
|
|
# define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value)) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key)) |
|
|
|
#else |
|
|
|
#else |
|
|
|
// Usually an int but a long on Cygwin64 with Python 3.x
|
|
|
|
# define PYBIND11_TLS_KEY_REF Py_tss_t * |
|
|
|
# define PYBIND11_TLS_KEY_REF decltype(PyThread_create_key()) |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr; |
|
|
|
# define PYBIND11_TLS_KEY_INIT(var) PYBIND11_TLS_KEY_REF var = 0; |
|
|
|
# define PYBIND11_TLS_KEY_CREATE(var) \ |
|
|
|
# define PYBIND11_TLS_KEY_CREATE(var) (((var) = PyThread_create_key()) != -1) |
|
|
|
(((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0)) |
|
|
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key)) |
|
|
|
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key)) |
|
|
|
# if defined(PYPY_VERSION) |
|
|
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value)) |
|
|
|
// On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
|
|
|
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr) |
|
|
|
// the value if it has already been set. Instead, it must first be deleted and
|
|
|
|
# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key) |
|
|
|
// then set again.
|
|
|
|
|
|
|
|
inline void tls_replace_value(PYBIND11_TLS_KEY_REF key, void *value) { |
|
|
|
|
|
|
|
PyThread_delete_key_value(key); |
|
|
|
|
|
|
|
PyThread_set_key_value(key, value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_delete_key_value(key) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \ |
|
|
|
|
|
|
|
::pybind11::detail::tls_replace_value((key), (value)) |
|
|
|
|
|
|
|
# else |
|
|
|
|
|
|
|
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_set_key_value((key), nullptr) |
|
|
|
|
|
|
|
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_set_key_value((key), (value)) |
|
|
|
|
|
|
|
# endif |
|
|
|
|
|
|
|
# define PYBIND11_TLS_FREE(key) (void) key |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
|
|
|
|
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
|
|
|
@ -216,28 +192,27 @@ struct internals { |
|
|
|
PyTypeObject *static_property_type; |
|
|
|
PyTypeObject *static_property_type; |
|
|
|
PyTypeObject *default_metaclass; |
|
|
|
PyTypeObject *default_metaclass; |
|
|
|
PyObject *instance_base; |
|
|
|
PyObject *instance_base; |
|
|
|
#if defined(WITH_THREAD) |
|
|
|
|
|
|
|
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
|
|
|
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
|
|
|
PYBIND11_TLS_KEY_INIT(tstate) |
|
|
|
PYBIND11_TLS_KEY_INIT(tstate) |
|
|
|
# if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
#if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key) |
|
|
|
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key) |
|
|
|
# endif // PYBIND11_INTERNALS_VERSION > 4
|
|
|
|
#endif // PYBIND11_INTERNALS_VERSION > 4
|
|
|
|
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
|
|
|
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
|
|
|
PyInterpreterState *istate = nullptr; |
|
|
|
PyInterpreterState *istate = nullptr; |
|
|
|
|
|
|
|
|
|
|
|
# if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
#if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
// Note that we have to use a std::string to allocate memory to ensure a unique address
|
|
|
|
// Note that we have to use a std::string to allocate memory to ensure a unique address
|
|
|
|
// We want unique addresses since we use pointer equality to compare function records
|
|
|
|
// We want unique addresses since we use pointer equality to compare function records
|
|
|
|
std::string function_record_capsule_name = internals_function_record_capsule_name; |
|
|
|
std::string function_record_capsule_name = internals_function_record_capsule_name; |
|
|
|
# endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
internals() = default; |
|
|
|
internals() = default; |
|
|
|
internals(const internals &other) = delete; |
|
|
|
internals(const internals &other) = delete; |
|
|
|
internals &operator=(const internals &other) = delete; |
|
|
|
internals &operator=(const internals &other) = delete; |
|
|
|
~internals() { |
|
|
|
~internals() { |
|
|
|
# if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
#if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
PYBIND11_TLS_FREE(loader_life_support_tls_key); |
|
|
|
PYBIND11_TLS_FREE(loader_life_support_tls_key); |
|
|
|
# endif // PYBIND11_INTERNALS_VERSION > 4
|
|
|
|
#endif // PYBIND11_INTERNALS_VERSION > 4
|
|
|
|
|
|
|
|
|
|
|
|
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
|
|
|
|
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
|
|
|
|
// That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
|
|
|
|
// That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
|
|
|
@ -248,7 +223,6 @@ struct internals { |
|
|
|
// that the `tstate` be allocated with the CPython allocator.
|
|
|
|
// that the `tstate` be allocated with the CPython allocator.
|
|
|
|
PYBIND11_TLS_FREE(tstate); |
|
|
|
PYBIND11_TLS_FREE(tstate); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/// Additional type information which does not fit into the PyTypeObject.
|
|
|
|
/// Additional type information which does not fit into the PyTypeObject.
|
|
|
@ -333,11 +307,7 @@ struct type_info { |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifndef PYBIND11_INTERNALS_KIND |
|
|
|
#ifndef PYBIND11_INTERNALS_KIND |
|
|
|
# if defined(WITH_THREAD) |
|
|
|
# define PYBIND11_INTERNALS_KIND "" |
|
|
|
# define PYBIND11_INTERNALS_KIND "" |
|
|
|
|
|
|
|
# else |
|
|
|
|
|
|
|
# define PYBIND11_INTERNALS_KIND "_without_thread" |
|
|
|
|
|
|
|
# endif |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#define PYBIND11_INTERNALS_ID \ |
|
|
|
#define PYBIND11_INTERNALS_ID \ |
|
|
@ -520,10 +490,9 @@ PYBIND11_NOINLINE internals &get_internals() { |
|
|
|
return **internals_pp; |
|
|
|
return **internals_pp; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_THREAD) |
|
|
|
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) |
|
|
|
# if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) |
|
|
|
|
|
|
|
gil_scoped_acquire gil; |
|
|
|
gil_scoped_acquire gil; |
|
|
|
# else |
|
|
|
#else |
|
|
|
// Ensure that the GIL is held since we will need to make Python calls.
|
|
|
|
// Ensure that the GIL is held since we will need to make Python calls.
|
|
|
|
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
|
|
|
|
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
|
|
|
|
struct gil_scoped_acquire_local { |
|
|
|
struct gil_scoped_acquire_local { |
|
|
@ -533,7 +502,6 @@ PYBIND11_NOINLINE internals &get_internals() { |
|
|
|
~gil_scoped_acquire_local() { PyGILState_Release(state); } |
|
|
|
~gil_scoped_acquire_local() { PyGILState_Release(state); } |
|
|
|
const PyGILState_STATE state; |
|
|
|
const PyGILState_STATE state; |
|
|
|
} gil; |
|
|
|
} gil; |
|
|
|
# endif |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
error_scope err_scope; |
|
|
|
error_scope err_scope; |
|
|
|
|
|
|
|
|
|
|
@ -558,7 +526,6 @@ PYBIND11_NOINLINE internals &get_internals() { |
|
|
|
} |
|
|
|
} |
|
|
|
auto *&internals_ptr = *internals_pp; |
|
|
|
auto *&internals_ptr = *internals_pp; |
|
|
|
internals_ptr = new internals(); |
|
|
|
internals_ptr = new internals(); |
|
|
|
#if defined(WITH_THREAD) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyThreadState *tstate = PyThreadState_Get(); |
|
|
|
PyThreadState *tstate = PyThreadState_Get(); |
|
|
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
|
|
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
|
|
@ -567,15 +534,14 @@ PYBIND11_NOINLINE internals &get_internals() { |
|
|
|
} |
|
|
|
} |
|
|
|
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate); |
|
|
|
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate); |
|
|
|
|
|
|
|
|
|
|
|
# if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
#if PYBIND11_INTERNALS_VERSION > 4 |
|
|
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
|
|
|
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
|
|
|
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->loader_life_support_tls_key)) { |
|
|
|
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->loader_life_support_tls_key)) { |
|
|
|
pybind11_fail("get_internals: could not successfully initialize the " |
|
|
|
pybind11_fail("get_internals: could not successfully initialize the " |
|
|
|
"loader_life_support TSS key!"); |
|
|
|
"loader_life_support TSS key!"); |
|
|
|
} |
|
|
|
} |
|
|
|
# endif |
|
|
|
|
|
|
|
internals_ptr->istate = tstate->interp; |
|
|
|
|
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
internals_ptr->istate = tstate->interp; |
|
|
|
state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp); |
|
|
|
state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp); |
|
|
|
internals_ptr->registered_exception_translators.push_front(&translate_exception); |
|
|
|
internals_ptr->registered_exception_translators.push_front(&translate_exception); |
|
|
|
internals_ptr->static_property_type = make_static_property_type(); |
|
|
|
internals_ptr->static_property_type = make_static_property_type(); |
|
|
@ -604,7 +570,7 @@ PYBIND11_NOINLINE internals &get_internals() { |
|
|
|
struct local_internals { |
|
|
|
struct local_internals { |
|
|
|
type_map<type_info *> registered_types_cpp; |
|
|
|
type_map<type_info *> registered_types_cpp; |
|
|
|
std::forward_list<ExceptionTranslator> registered_exception_translators; |
|
|
|
std::forward_list<ExceptionTranslator> registered_exception_translators; |
|
|
|
#if defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4 |
|
|
|
#if PYBIND11_INTERNALS_VERSION == 4 |
|
|
|
|
|
|
|
|
|
|
|
// For ABI compatibility, we can't store the loader_life_support TLS key in
|
|
|
|
// For ABI compatibility, we can't store the loader_life_support TLS key in
|
|
|
|
// the `internals` struct directly. Instead, we store it in `shared_data` and
|
|
|
|
// the `internals` struct directly. Instead, we store it in `shared_data` and
|
|
|
@ -637,7 +603,7 @@ struct local_internals { |
|
|
|
loader_life_support_tls_key |
|
|
|
loader_life_support_tls_key |
|
|
|
= static_cast<shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key; |
|
|
|
= static_cast<shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif // defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
|
|
|
|
#endif // PYBIND11_INTERNALS_VERSION == 4
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/// Works like `get_internals`, but for things which are locally registered.
|
|
|
|
/// Works like `get_internals`, but for things which are locally registered.
|
|
|
|