@@ -54,6 +54,7 @@ constexpr const char *internals_function_record_capsule_name = "pybind11_functio
54
54
inline PyTypeObject *make_static_property_type ();
55
55
inline PyTypeObject *make_default_metaclass ();
56
56
inline PyObject *make_object_base_type (PyTypeObject *metaclass);
57
+ inline void translate_exception (std::exception_ptr p);
57
58
58
59
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
59
60
// Thread Specific Storage (TSS) API.
@@ -179,9 +180,9 @@ struct internals {
179
180
// extensions
180
181
std::forward_list<std::string> static_strings; // Stores the std::strings backing
181
182
// detail::c_str()
182
- PyTypeObject *static_property_type;
183
- PyTypeObject *default_metaclass;
184
- PyObject *instance_base;
183
+ PyTypeObject *static_property_type = nullptr ;
184
+ PyTypeObject *default_metaclass = nullptr ;
185
+ PyObject *instance_base = nullptr ;
185
186
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
186
187
PYBIND11_TLS_KEY_INIT (tstate)
187
188
PYBIND11_TLS_KEY_INIT (loader_life_support_tls_key)
@@ -190,7 +191,36 @@ struct internals {
190
191
191
192
type_map<PyObject *> native_enum_type_map;
192
193
193
- internals () = default ;
194
+ internals () {
195
+ PyThreadState *curtstate = PyThreadState_Get ();
196
+ // NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
197
+ if (!PYBIND11_TLS_KEY_CREATE (tstate)) {
198
+ pybind11_fail (
199
+ " internals constructor: could not successfully initialize the tstate TSS key!" );
200
+ }
201
+ PYBIND11_TLS_REPLACE_VALUE (tstate, curtstate);
202
+
203
+ // NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
204
+ if (!PYBIND11_TLS_KEY_CREATE (loader_life_support_tls_key)) {
205
+ pybind11_fail (" internals constructor: could not successfully initialize the "
206
+ " loader_life_support TSS key!" );
207
+ }
208
+
209
+ istate = curtstate->interp ;
210
+ registered_exception_translators.push_front (&translate_exception);
211
+ static_property_type = make_static_property_type ();
212
+ default_metaclass = make_default_metaclass ();
213
+ #ifdef Py_GIL_DISABLED
214
+ // Scale proportional to the number of cores. 2x is a heuristic to reduce contention.
215
+ auto num_shards
216
+ = static_cast <size_t >(round_up_to_next_pow2 (2 * std::thread::hardware_concurrency ()));
217
+ if (num_shards == 0 ) {
218
+ num_shards = 1 ;
219
+ }
220
+ instance_shards.reset (new instance_map_shard[num_shards]);
221
+ instance_shards_mask = num_shards - 1 ;
222
+ #endif
223
+ }
194
224
internals (const internals &other) = delete ;
195
225
internals &operator =(const internals &other) = delete ;
196
226
~internals () {
@@ -461,18 +491,25 @@ inline InternalsType **get_internals_pp_from_capsule_in_state_dict(dict &state_d
461
491
PYBIND11_NOINLINE internals &get_internals () {
462
492
auto **&internals_pp = get_internals_pp ();
463
493
if (internals_pp && *internals_pp) {
494
+ // This is the fast path, everything is already setup, just return it
464
495
return **internals_pp;
465
496
}
466
497
498
+ // Slow path, something needs fetched from the state dict or created
499
+
467
500
// Cannot use py::gil_scoped_acquire inside get_internals since that calls get_internals.
468
501
gil_scoped_acquire_simple gil;
469
502
error_scope err_scope;
470
503
471
504
dict state_dict = get_python_state_dict ();
472
505
internals_pp = get_internals_pp_from_capsule_in_state_dict<internals>(state_dict,
473
506
PYBIND11_INTERNALS_ID);
507
+ if (!internals_pp) {
508
+ internals_pp = new internals *(nullptr );
509
+ state_dict[PYBIND11_INTERNALS_ID] = capsule (reinterpret_cast <void *>(internals_pp));
510
+ }
474
511
475
- if (internals_pp && *internals_pp) {
512
+ if (*internals_pp) {
476
513
// We loaded the internals through `state_dict`, which means that our `error_already_set`
477
514
// and `builtin_exception` may be different local classes than the ones set up in the
478
515
// initial exception translator, below, so add another for our local exception classes.
@@ -489,43 +526,16 @@ PYBIND11_NOINLINE internals &get_internals() {
489
526
}
490
527
#endif
491
528
} else {
492
- if (!internals_pp) {
493
- internals_pp = new internals *(nullptr );
494
- state_dict[PYBIND11_INTERNALS_ID] = capsule (reinterpret_cast <void *>(internals_pp));
495
- }
496
-
497
- auto *&internals_ptr = *internals_pp;
529
+ auto &internals_ptr = *internals_pp;
498
530
internals_ptr = new internals ();
499
531
500
- PyThreadState *tstate = PyThreadState_Get ();
501
- // NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
502
- if (! PYBIND11_TLS_KEY_CREATE ( internals_ptr-> tstate )) {
503
- pybind11_fail ( " get_internals: could not successfully initialize the tstate TSS key! " );
532
+ if (!internals_ptr-> instance_base ) {
533
+ // This calls get_internals, so cannot be called from within the internals constructor
534
+ // called above because internals_ptr must be set before get_internals is called again
535
+ internals_ptr-> instance_base = make_object_base_type (internals_ptr-> default_metaclass );
504
536
}
505
- PYBIND11_TLS_REPLACE_VALUE (internals_ptr->tstate , tstate);
506
-
507
- // NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
508
- if (!PYBIND11_TLS_KEY_CREATE (internals_ptr->loader_life_support_tls_key )) {
509
- pybind11_fail (" get_internals: could not successfully initialize the "
510
- " loader_life_support TSS key!" );
511
- }
512
-
513
- internals_ptr->istate = tstate->interp ;
514
- internals_ptr->registered_exception_translators .push_front (&translate_exception);
515
- internals_ptr->static_property_type = make_static_property_type ();
516
- internals_ptr->default_metaclass = make_default_metaclass ();
517
- internals_ptr->instance_base = make_object_base_type (internals_ptr->default_metaclass );
518
- #ifdef Py_GIL_DISABLED
519
- // Scale proportional to the number of cores. 2x is a heuristic to reduce contention.
520
- auto num_shards
521
- = static_cast <size_t >(round_up_to_next_pow2 (2 * std::thread::hardware_concurrency ()));
522
- if (num_shards == 0 ) {
523
- num_shards = 1 ;
524
- }
525
- internals_ptr->instance_shards .reset (new instance_map_shard[num_shards]);
526
- internals_ptr->instance_shards_mask = num_shards - 1 ;
527
- #endif // Py_GIL_DISABLED
528
537
}
538
+
529
539
return **internals_pp;
530
540
}
531
541
0 commit comments