11
11
12
12
#include " ../pytypes.h"
13
13
14
+ // / Tracks the `internals` and `type_info` ABI version independent of the main library version.
15
+ // /
16
+ // / Some portions of the code use an ABI that is conditional depending on this
17
+ // / version number. That allows ABI-breaking changes to be "pre-implemented".
18
+ // / Once the default version number is incremented, the conditional logic that
19
+ // / no longer applies can be removed. Additionally, users that need not
20
+ // / maintain ABI compatibility can increase the version number in order to take
21
+ // / advantage of any functionality/efficiency improvements that depend on the
22
+ // / newer ABI.
23
+ #ifndef PYBIND11_INTERNALS_VERSION
24
+ #define PYBIND11_INTERNALS_VERSION 4
25
+ #endif
26
+
14
27
PYBIND11_NAMESPACE_BEGIN (PYBIND11_NAMESPACE)
15
28
16
29
using ExceptionTranslator = void (*)(std::exception_ptr);
@@ -25,30 +38,44 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
25
38
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
26
39
// Thread Specific Storage (TSS) API.
27
40
#if PY_VERSION_HEX >= 0x03070000
28
- # define PYBIND11_TLS_KEY_INIT (var ) Py_tss_t *var = nullptr
29
- # define PYBIND11_TLS_GET_VALUE (key ) PyThread_tss_get((key))
30
- # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_tss_set((key), (value))
31
- # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_tss_set((key), nullptr )
32
- # define PYBIND11_TLS_FREE (key ) PyThread_tss_free(key)
41
+ // Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
42
+ // `Py_LIMITED_API` anyway.
43
+ # if PYBIND11_INTERNALS_VERSION > 4
44
+ # define PYBIND11_TLS_KEY_REF Py_tss_t &
45
+ # define PYBIND11_TLS_KEY_INIT (var ) Py_tss_t var = Py_tss_NEEDS_INIT
46
+ # define PYBIND11_TLS_KEY_CREATE (var ) (PyThread_tss_create(&(var)) == 0 )
47
+ # define PYBIND11_TLS_GET_VALUE (key ) PyThread_tss_get(&(key))
48
+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_tss_set(&(key), (value))
49
+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_tss_set(&(key), nullptr )
50
+ # define PYBIND11_TLS_FREE (key ) PyThread_tss_delete(&(key))
51
+ # else
52
+ # define PYBIND11_TLS_KEY_REF Py_tss_t *
53
+ # define PYBIND11_TLS_KEY_INIT (var ) Py_tss_t *var = nullptr
54
+ # define PYBIND11_TLS_KEY_CREATE (var ) \
55
+ (((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0 ))
56
+ # define PYBIND11_TLS_GET_VALUE (key ) PyThread_tss_get((key))
57
+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_tss_set((key), (value))
58
+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_tss_set((key), nullptr )
59
+ # define PYBIND11_TLS_FREE (key ) PyThread_tss_free(key)
60
+ # endif
33
61
#else
34
- // Usually an int but a long on Cygwin64 with Python 3.x
35
- # define PYBIND11_TLS_KEY_INIT (var ) decltype(PyThread_create_key()) var = 0
62
+ // Usually an int but a long on Cygwin64 with Python 3.x
63
+ # define PYBIND11_TLS_KEY_REF decltype (PyThread_create_key())
64
+ # define PYBIND11_TLS_KEY_INIT (var ) PYBIND11_TLS_KEY_REF var = 0
65
+ # define PYBIND11_TLS_KEY_CREATE (var ) (((var) = PyThread_create_key()) != -1 )
36
66
# define PYBIND11_TLS_GET_VALUE (key ) PyThread_get_key_value((key))
37
67
# if PY_MAJOR_VERSION < 3
38
- # define PYBIND11_TLS_DELETE_VALUE (key ) \
39
- PyThread_delete_key_value (key)
40
- # define PYBIND11_TLS_REPLACE_VALUE (key, value ) \
41
- do { \
42
- PyThread_delete_key_value ((key)); \
43
- PyThread_set_key_value ((key), (value)); \
44
- } while (false )
68
+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_delete_key_value(key)
69
+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) \
70
+ do { \
71
+ PyThread_delete_key_value ((key)); \
72
+ PyThread_set_key_value ((key), (value)); \
73
+ } while (false )
45
74
# else
46
- # define PYBIND11_TLS_DELETE_VALUE (key ) \
47
- PyThread_set_key_value ((key), nullptr)
48
- # define PYBIND11_TLS_REPLACE_VALUE (key, value ) \
49
- PyThread_set_key_value ((key), (value))
75
+ # define PYBIND11_TLS_DELETE_VALUE (key ) PyThread_set_key_value((key), nullptr )
76
+ # define PYBIND11_TLS_REPLACE_VALUE (key, value ) PyThread_set_key_value((key), (value))
50
77
# endif
51
- # define PYBIND11_TLS_FREE (key ) (void )key
78
+ # define PYBIND11_TLS_FREE (key ) (void ) key
52
79
#endif
53
80
54
81
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
@@ -106,22 +133,31 @@ struct internals {
106
133
std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
107
134
std::forward_list<ExceptionTranslator> registered_exception_translators;
108
135
std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
136
+ #if PYBIND11_INTERNALS_VERSION == 4
109
137
std::vector<PyObject *> unused_loader_patient_stack_remove_at_v5;
138
+ #endif
110
139
std::forward_list<std::string> static_strings; // Stores the std::strings backing detail::c_str()
111
140
PyTypeObject *static_property_type;
112
141
PyTypeObject *default_metaclass;
113
142
PyObject *instance_base;
114
143
#if defined(WITH_THREAD)
115
144
PYBIND11_TLS_KEY_INIT (tstate);
145
+ # if PYBIND11_INTERNALS_VERSION > 4
146
+ PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key);
147
+ # endif // PYBIND11_INTERNALS_VERSION > 4
116
148
PyInterpreterState *istate = nullptr ;
117
149
~internals () {
150
+ # if PYBIND11_INTERNALS_VERSION > 4
151
+ PYBIND11_TLS_FREE (loader_life_support_tls_key);
152
+ # endif // PYBIND11_INTERNALS_VERSION > 4
153
+
118
154
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
119
- // That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is called.
120
- // PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does nothing.
121
- // PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
122
- // PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX). Neither
123
- // of those have anything to do with CPython internals.
124
- // PyMem_RawFree *requires* that the `tstate` be allocated with the CPython allocator.
155
+ // That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
156
+ // called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
157
+ // nothing. PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
158
+ // PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX).
159
+ // Neither of those have anything to do with CPython internals. PyMem_RawFree *requires*
160
+ // that the `tstate` be allocated with the CPython allocator.
125
161
PYBIND11_TLS_FREE (tstate);
126
162
}
127
163
#endif
@@ -153,9 +189,6 @@ struct type_info {
153
189
bool module_local : 1 ;
154
190
};
155
191
156
- // / Tracks the `internals` and `type_info` ABI version independent of the main library version
157
- #define PYBIND11_INTERNALS_VERSION 4
158
-
159
192
// / On MSVC, debug and release builds are not ABI-compatible!
160
193
#if defined(_MSC_VER) && defined(_DEBUG)
161
194
# define PYBIND11_BUILD_TYPE " _debug"
@@ -291,21 +324,21 @@ PYBIND11_NOINLINE internals &get_internals() {
291
324
internals_ptr = new internals ();
292
325
#if defined(WITH_THREAD)
293
326
294
- # if PY_VERSION_HEX < 0x03090000
295
- PyEval_InitThreads ();
296
- # endif
327
+ # if PY_VERSION_HEX < 0x03090000
328
+ PyEval_InitThreads ();
329
+ # endif
297
330
PyThreadState *tstate = PyThreadState_Get ();
298
- # if PY_VERSION_HEX >= 0x03070000
299
- internals_ptr-> tstate = PyThread_tss_alloc ( );
300
- if (!internals_ptr-> tstate || ( PyThread_tss_create (internals_ptr-> tstate ) != 0 ))
301
- pybind11_fail ( " get_internals: could not successfully initialize the tstate TSS key! " );
302
- PyThread_tss_set (internals_ptr-> tstate , tstate);
303
- # else
304
- internals_ptr->tstate = PyThread_create_key ();
305
- if (internals_ptr-> tstate == - 1 )
306
- pybind11_fail ( " get_internals: could not successfully initialize the tstate TLS key!" );
307
- PyThread_set_key_value (internals_ptr-> tstate , tstate);
308
- # endif
331
+ if (! PYBIND11_TLS_KEY_CREATE (internals_ptr-> tstate )) {
332
+ pybind11_fail ( " get_internals: could not successfully initialize the tstate TSS key! " );
333
+ }
334
+ PYBIND11_TLS_REPLACE_VALUE (internals_ptr-> tstate , tstate );
335
+
336
+ # if PYBIND11_INTERNALS_VERSION > 4
337
+ if (! PYBIND11_TLS_KEY_CREATE ( internals_ptr->loader_life_support_tls_key )) {
338
+ pybind11_fail ( " get_internals: could not successfully initialize the "
339
+ " loader_life_support TSS key!" );
340
+ }
341
+ # endif
309
342
internals_ptr->istate = tstate->interp ;
310
343
#endif
311
344
builtins[id] = capsule (internals_pp);
@@ -317,16 +350,48 @@ PYBIND11_NOINLINE internals &get_internals() {
317
350
return **internals_pp;
318
351
}
319
352
320
-
321
353
// the internals struct (above) is shared between all the modules. local_internals are only
322
354
// for a single module. Any changes made to internals may require an update to
323
355
// PYBIND11_INTERNALS_VERSION, breaking backwards compatibility. local_internals is, by design,
324
356
// restricted to a single module. Whether a module has local internals or not should not
325
357
// impact any other modules, because the only things accessing the local internals is the
326
358
// module that contains them.
327
359
struct local_internals {
328
- type_map<type_info *> registered_types_cpp;
329
- std::forward_list<ExceptionTranslator> registered_exception_translators;
360
+ type_map<type_info *> registered_types_cpp;
361
+ std::forward_list<ExceptionTranslator> registered_exception_translators;
362
+ #if defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
363
+
364
+ // For ABI compatibility, we can't store the loader_life_support TLS key in
365
+ // the `internals` struct directly. Instead, we store it in `shared_data` and
366
+ // cache a copy in `local_internals`. If we allocated a separate TLS key for
367
+ // each instance of `local_internals`, we could end up allocating hundreds of
368
+ // TLS keys if hundreds of different pybind11 modules are loaded (which is a
369
+ // plausible number).
370
+ PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key);
371
+
372
+ // Holds the shared TLS key for the loader_life_support stack.
373
+ struct shared_loader_life_support_data {
374
+ PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key);
375
+ shared_loader_life_support_data () {
376
+ if (!PYBIND11_TLS_KEY_CREATE (loader_life_support_tls_key)) {
377
+ pybind11_fail (" local_internals: could not successfully initialize the "
378
+ " loader_life_support TLS key!" );
379
+ }
380
+ }
381
+ // We can't help but leak the TLS key, because Python never unloads extension modules.
382
+ };
383
+
384
+ local_internals () {
385
+ auto &internals = get_internals ();
386
+ // Get or create the `loader_life_support_stack_key`.
387
+ auto &ptr = internals.shared_data [" _life_support" ];
388
+ if (!ptr) {
389
+ ptr = new shared_loader_life_support_data;
390
+ }
391
+ loader_life_support_tls_key
392
+ = static_cast <shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key ;
393
+ }
394
+ #endif // defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
330
395
};
331
396
332
397
// / Works like `get_internals`, but for things which are locally registered.
0 commit comments