@@ -205,39 +205,40 @@ extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, P
205205
206206// / Cleanup the type-info for a pybind11-registered type.
207207extern " C" inline void pybind11_meta_dealloc (PyObject *obj) {
208- auto *type = (PyTypeObject *) obj;
209- auto &internals = get_internals ();
210-
211- // A pybind11-registered type will:
212- // 1) be found in internals.registered_types_py
213- // 2) have exactly one associated `detail::type_info`
214- auto found_type = internals.registered_types_py .find (type);
215- if (found_type != internals.registered_types_py .end () && found_type->second .size () == 1
216- && found_type->second [0 ]->type == type) {
217-
218- auto *tinfo = found_type->second [0 ];
219- auto tindex = std::type_index (*tinfo->cpptype );
220- internals.direct_conversions .erase (tindex);
221-
222- if (tinfo->module_local ) {
223- get_local_internals ().registered_types_cpp .erase (tindex);
224- } else {
225- internals.registered_types_cpp .erase (tindex);
226- }
227- internals.registered_types_py .erase (tinfo->type );
228-
229- // Actually just `std::erase_if`, but that's only available in C++20
230- auto &cache = internals.inactive_override_cache ;
231- for (auto it = cache.begin (), last = cache.end (); it != last;) {
232- if (it->first == (PyObject *) tinfo->type ) {
233- it = cache.erase (it);
208+ with_internals ([obj](internals &internals) {
209+ auto *type = (PyTypeObject *) obj;
210+
211+ // A pybind11-registered type will:
212+ // 1) be found in internals.registered_types_py
213+ // 2) have exactly one associated `detail::type_info`
214+ auto found_type = internals.registered_types_py .find (type);
215+ if (found_type != internals.registered_types_py .end () && found_type->second .size () == 1
216+ && found_type->second [0 ]->type == type) {
217+
218+ auto *tinfo = found_type->second [0 ];
219+ auto tindex = std::type_index (*tinfo->cpptype );
220+ internals.direct_conversions .erase (tindex);
221+
222+ if (tinfo->module_local ) {
223+ get_local_internals ().registered_types_cpp .erase (tindex);
234224 } else {
235- ++it;
225+ internals.registered_types_cpp .erase (tindex);
226+ }
227+ internals.registered_types_py .erase (tinfo->type );
228+
229+ // Actually just `std::erase_if`, but that's only available in C++20
230+ auto &cache = internals.inactive_override_cache ;
231+ for (auto it = cache.begin (), last = cache.end (); it != last;) {
232+ if (it->first == (PyObject *) tinfo->type ) {
233+ it = cache.erase (it);
234+ } else {
235+ ++it;
236+ }
236237 }
237- }
238238
239- delete tinfo;
240- }
239+ delete tinfo;
240+ }
241+ });
241242
242243 PyType_Type.tp_dealloc (obj);
243244}
@@ -310,19 +311,20 @@ inline void traverse_offset_bases(void *valueptr,
310311}
311312
312313inline bool register_instance_impl (void *ptr, instance *self) {
313- get_internals (). registered_instances . emplace (ptr, self);
314+ with_instance_map (ptr, [&](instance_map &instances) { instances. emplace (ptr, self); } );
314315 return true ; // unused, but gives the same signature as the deregister func
315316}
316317inline bool deregister_instance_impl (void *ptr, instance *self) {
317- auto ®istered_instances = get_internals ().registered_instances ;
318- auto range = registered_instances.equal_range (ptr);
319- for (auto it = range.first ; it != range.second ; ++it) {
320- if (self == it->second ) {
321- registered_instances.erase (it);
322- return true ;
318+ return with_instance_map (ptr, [&](instance_map &instances) {
319+ auto range = instances.equal_range (ptr);
320+ for (auto it = range.first ; it != range.second ; ++it) {
321+ if (self == it->second ) {
322+ instances.erase (it);
323+ return true ;
324+ }
323325 }
324- }
325- return false ;
326+ return false ;
327+ }) ;
326328}
327329
328330inline void register_instance (instance *self, void *valptr, const type_info *tinfo) {
@@ -377,27 +379,32 @@ extern "C" inline int pybind11_object_init(PyObject *self, PyObject *, PyObject
377379}
378380
379381inline void add_patient (PyObject *nurse, PyObject *patient) {
380- auto &internals = get_internals ();
381382 auto *instance = reinterpret_cast <detail::instance *>(nurse);
382383 instance->has_patients = true ;
383384 Py_INCREF (patient);
384- internals.patients [nurse].push_back (patient);
385+
386+ with_internals ([&](internals &internals) { internals.patients [nurse].push_back (patient); });
385387}
386388
387389inline void clear_patients (PyObject *self) {
388390 auto *instance = reinterpret_cast <detail::instance *>(self);
389- auto &internals = get_internals ();
390- auto pos = internals.patients .find (self);
391+ std::vector<PyObject *> patients;
391392
392- if (pos == internals.patients .end ()) {
393- pybind11_fail (" FATAL: Internal consistency check failed: Invalid clear_patients() call." );
394- }
393+ with_internals ([&](internals &internals) {
394+ auto pos = internals.patients .find (self);
395+
396+ if (pos == internals.patients .end ()) {
397+ pybind11_fail (
398+ " FATAL: Internal consistency check failed: Invalid clear_patients() call." );
399+ }
400+
401+ // Clearing the patients can cause more Python code to run, which
402+ // can invalidate the iterator. Extract the vector of patients
403+ // from the unordered_map first.
404+ patients = std::move (pos->second );
405+ internals.patients .erase (pos);
406+ });
395407
396- // Clearing the patients can cause more Python code to run, which
397- // can invalidate the iterator. Extract the vector of patients
398- // from the unordered_map first.
399- auto patients = std::move (pos->second );
400- internals.patients .erase (pos);
401408 instance->has_patients = false ;
402409 for (PyObject *&patient : patients) {
403410 Py_CLEAR (patient);
@@ -662,10 +669,13 @@ inline PyObject *make_new_python_type(const type_record &rec) {
662669
663670 char *tp_doc = nullptr ;
664671 if (rec.doc && options::show_user_defined_docstrings ()) {
665- /* Allocate memory for docstring (using PyObject_MALLOC, since
666- Python will free this later on) */
672+ /* Allocate memory for docstring (Python will free this later on) */
667673 size_t size = std::strlen (rec.doc ) + 1 ;
674+ #if PY_VERSION_HEX >= 0x030D0000
675+ tp_doc = (char *) PyMem_MALLOC (size);
676+ #else
668677 tp_doc = (char *) PyObject_MALLOC (size);
678+ #endif
669679 std::memcpy ((void *) tp_doc, rec.doc , size);
670680 }
671681
0 commit comments