@@ -80,7 +80,8 @@ class thread_specific_storage {
8080 thread_specific_storage () {
8181 // NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
8282 if (!PYBIND11_TLS_KEY_CREATE (key_)) {
83- pybind11_fail (" thread_local_storage constructor: could not initialize the TSS key!" );
83+ pybind11_fail (
84+ " thread_specific_storage constructor: could not initialize the TSS key!" );
8485 }
8586 }
8687
@@ -115,7 +116,7 @@ class thread_specific_storage {
115116 }
116117
117118private:
118- PYBIND11_TLS_KEY_INIT (mutable key_);
119+ PYBIND11_TLS_KEY_INIT (mutable key_)
119120};
120121
121122PYBIND11_NAMESPACE_BEGIN (detail)
@@ -476,7 +477,9 @@ inline object get_python_state_dict() {
476477template <typename InternalsType>
477478class internals_pp_manager {
478479public:
479- explicit internals_pp_manager (char const *id) : holder_id_(id) {}
480+ using on_fetch_function = void (InternalsType *);
481+ explicit internals_pp_manager (char const *id, on_fetch_function *on_fetch = nullptr )
482+ : holder_id_(id), on_fetch_(on_fetch) {}
480483
481484 // / Get the current pointer-to-pointer, allocating it if it does not already exist. May
482485 // / acquire the GIL. Will never return nullptr.
@@ -539,7 +542,7 @@ class internals_pp_manager {
539542 dict state_dict = get_python_state_dict ();
540543 auto internals_obj
541544 = reinterpret_steal<object>(dict_getitemstringref (state_dict.ptr (), holder_id_));
542- std::unique_ptr<InternalsType> *pp;
545+ std::unique_ptr<InternalsType> *pp = nullptr ;
543546 if (internals_obj) {
544547 void *raw_ptr = PyCapsule_GetPointer (internals_obj.ptr (), /* name=*/ nullptr );
545548 if (!raw_ptr) {
@@ -548,46 +551,57 @@ class internals_pp_manager {
548551 throw error_already_set ();
549552 }
550553 pp = reinterpret_cast <std::unique_ptr<InternalsType> *>(raw_ptr);
554+ if (on_fetch_ && pp) {
555+ on_fetch_ (pp->get ());
556+ }
551557 } else {
552558 pp = new std::unique_ptr<InternalsType>;
559+ // NOLINTNEXTLINE(bugprone-casting-through-void)
553560 state_dict[holder_id_] = capsule (reinterpret_cast <void *>(pp));
554561 }
555562 return pp;
556563 }
557564
558565 char const *holder_id_ = nullptr ;
566+ on_fetch_function *on_fetch_ = nullptr ;
559567#if PYBIND11_HAS_SUBINTERPRETER_SUPPORT
560568 thread_specific_storage<PyInterpreterState> last_istate_;
561569 thread_specific_storage<std::unique_ptr<InternalsType>> internals_tls_p_;
562570#endif
563571 std::unique_ptr<InternalsType> *internals_singleton_pp_;
564572};
565573
574+ inline void on_internals_fetch (internals *internals_ptr) {
575+ // If We loaded the internals through `state_dict`, our `error_already_set`
576+ // and `builtin_exception` may be different local classes than the ones set up in the
577+ // initial exception translator, below, so add another for our local exception classes.
578+ //
579+ // libstdc++ doesn't require this (types there are identified only by name)
580+ // libc++ with CPython doesn't require this (types are explicitly exported)
581+ // libc++ with PyPy still need it, awaiting further investigation
582+ if (internals_ptr) {
583+ #if !defined(__GLIBCXX__)
584+ for (auto et : internals_ptr->registered_exception_translators ) {
585+ if (et == &translate_local_exception) {
586+ return ;
587+ }
588+ }
589+ internals_ptr->registered_exception_translators .push_front (&translate_local_exception);
590+ #endif
591+ }
592+ }
593+
566594inline internals_pp_manager<internals> &get_internals_pp_manager () {
567- static internals_pp_manager<internals> internals_pp_manager (PYBIND11_INTERNALS_ID);
595+ static internals_pp_manager<internals> internals_pp_manager (PYBIND11_INTERNALS_ID,
596+ &on_internals_fetch);
568597 return internals_pp_manager;
569598}
570599
571600// / Return a reference to the current `internals` data
572601PYBIND11_NOINLINE internals &get_internals () {
573602 auto &ppmgr = get_internals_pp_manager ();
574603 auto &internals_ptr = *ppmgr.get_pp ();
575- if (internals_ptr) {
576- // If We loaded the internals through `state_dict`, our `error_already_set`
577- // and `builtin_exception` may be different local classes than the ones set up in the
578- // initial exception translator, below, so add another for our local exception classes.
579- //
580- // libstdc++ doesn't require this (types there are identified only by name)
581- // libc++ with CPython doesn't require this (types are explicitly exported)
582- // libc++ with PyPy still need it, awaiting further investigation
583- #if !defined(__GLIBCXX__)
584- if (internals_ptr->registered_exception_translators .empty ()
585- || internals_ptr->registered_exception_translators .front ()
586- != &translate_local_exception) {
587- internals_ptr->registered_exception_translators .push_front (&translate_local_exception);
588- }
589- #endif
590- } else {
604+ if (!internals_ptr) {
591605 // Slow path, something needs fetched from the state dict or created
592606 gil_scoped_acquire_simple gil;
593607 error_scope err_scope;
0 commit comments