@@ -311,6 +311,8 @@ struct type_info {
311
311
// / Each module locally stores a pointer to the `internals` data. The data
312
312
// / itself is shared among modules with the same `PYBIND11_INTERNALS_ID`.
313
313
inline internals **&get_internals_pp () {
314
+ // The reason for the double-indirection is documented here:
315
+ // https://github.com/pybind/pybind11/pull/1092
314
316
static internals **internals_pp = nullptr ;
315
317
return internals_pp;
316
318
}
@@ -647,52 +649,81 @@ T &get_or_create_shared_data(const std::string &name) {
647
649
648
650
PYBIND11_NAMESPACE_BEGIN (detail)
649
651
650
- #define PYBIND11_NATIVE_ENUM_TYPE_MAP_ABI_ID \
651
- " __pybind11_native_enum_type_map_v1" PYBIND11_ABI_ID " __"
652
+ struct native_enum_type_map_v1 {
653
+ static constexpr const char *abi_id_c_str
654
+ = " __pybind11_native_enum_type_map_v1" PYBIND11_ABI_ID " __" ;
652
655
653
- using native_enum_type_map = type_map<PyObject *>;
656
+ using native_enum_type_map = type_map<PyObject *>;
654
657
655
- inline native_enum_type_map **&get_native_enum_types_pp () {
656
- static native_enum_type_map **native_enum_types_pp = nullptr ;
657
- return native_enum_types_pp;
658
- }
659
-
660
- PYBIND11_NOINLINE native_enum_type_map &get_native_enum_type_map () {
661
- native_enum_type_map **&native_enum_type_map_pp = get_native_enum_types_pp ();
662
- if (native_enum_type_map_pp && *native_enum_type_map_pp) {
663
- return **native_enum_type_map_pp;
658
+ static native_enum_type_map **&native_enum_type_map_pp () {
659
+ static native_enum_type_map **pp;
660
+ return pp;
664
661
}
665
662
666
- gil_scoped_acquire_simple gil;
667
- error_scope err_scope;
663
+ static native_enum_type_map *get_existing () {
664
+ if (native_enum_type_map_pp () && *native_enum_type_map_pp ()) {
665
+ return *native_enum_type_map_pp ();
666
+ }
668
667
669
- constexpr const char *id_cstr = PYBIND11_NATIVE_ENUM_TYPE_MAP_ABI_ID ;
670
- str id (id_cstr) ;
668
+ gil_scoped_acquire_simple gil ;
669
+ error_scope err_scope ;
671
670
672
- dict state_dict = get_python_state_dict ();
671
+ str abi_id_str (abi_id_c_str);
672
+ dict state_dict = get_python_state_dict ();
673
+ if (!state_dict.contains (abi_id_str)) {
674
+ return nullptr ;
675
+ }
673
676
674
- if (state_dict.contains (id_cstr)) {
675
- void *raw_ptr = PyCapsule_GetPointer (state_dict[id].ptr (), id_cstr);
677
+ void *raw_ptr = PyCapsule_GetPointer (state_dict[abi_id_str].ptr (), abi_id_c_str);
676
678
if (raw_ptr == nullptr ) {
677
679
raise_from (PyExc_SystemError,
678
- " pybind11::detail::get_native_enum_type_map (): Retrieve "
679
- " native_enum_type_map** from capsule FAILED" );
680
+ " pybind11::detail::native_enum_type_map::get_existing ():"
681
+ " Retrieve native_enum_type_map** from capsule FAILED" );
680
682
}
681
- native_enum_type_map_pp = static_cast <native_enum_type_map **>(raw_ptr);
683
+ native_enum_type_map_pp () = static_cast <native_enum_type_map **>(raw_ptr);
684
+ return *native_enum_type_map_pp ();
682
685
}
683
686
684
- if (native_enum_type_map_pp && *native_enum_type_map_pp) {
685
- return **native_enum_type_map_pp;
687
+ static native_enum_type_map &get () {
688
+ if (get_existing () != nullptr ) {
689
+ return **native_enum_type_map_pp ();
690
+ }
691
+ if (native_enum_type_map_pp () == nullptr ) {
692
+ native_enum_type_map_pp () = new native_enum_type_map *();
693
+ }
694
+ *native_enum_type_map_pp () = new native_enum_type_map ();
695
+ get_python_state_dict ()[abi_id_c_str] = capsule (native_enum_type_map_pp (), abi_id_c_str);
696
+ return **native_enum_type_map_pp ();
686
697
}
687
698
688
- if (!native_enum_type_map_pp) {
689
- native_enum_type_map_pp = new native_enum_type_map *();
690
- }
691
- auto *&native_enum_type_map_ptr = *native_enum_type_map_pp;
692
- native_enum_type_map_ptr = new native_enum_type_map ();
693
- state_dict[id] = capsule (native_enum_type_map_pp, id_cstr);
694
- return **native_enum_type_map_pp;
695
- }
699
+ struct scoped_clear {
700
+ // To be called BEFORE Py_Finalize().
701
+ scoped_clear () {
702
+ if (get_existing () != nullptr ) {
703
+ for (auto it : **native_enum_type_map_pp ()) {
704
+ Py_DECREF (it.second );
705
+ }
706
+ (*native_enum_type_map_pp ())->clear ();
707
+ arm_dtor = true ;
708
+ }
709
+ }
710
+
711
+ // To be called AFTER Py_Finalize().
712
+ ~scoped_clear () {
713
+ if (arm_dtor) {
714
+ delete *native_enum_type_map_pp ();
715
+ *native_enum_type_map_pp () = nullptr ;
716
+ }
717
+ }
718
+
719
+ scoped_clear (const scoped_clear &) = delete ;
720
+ scoped_clear &operator =(const scoped_clear &) = delete ;
721
+
722
+ bool arm_dtor = false ;
723
+ };
724
+ };
725
+
726
+ using native_enum_type_map = native_enum_type_map_v1;
696
727
697
728
PYBIND11_NAMESPACE_END (detail)
698
729
0 commit comments