18
18
#include " type_caster_base.h"
19
19
#include " typeid.h"
20
20
21
+ #include < cassert>
21
22
#include < cstddef>
22
23
#include < memory>
23
24
#include < new>
@@ -343,6 +344,18 @@ struct smart_holder_type_caster_class_hooks : smart_holder_type_caster_base_tag
343
344
}
344
345
};
345
346
347
+ struct shared_ptr_trampoline_self_life_support {
348
+ PyObject *self;
349
+ explicit shared_ptr_trampoline_self_life_support (instance *inst)
350
+ : self{reinterpret_cast <PyObject *>(inst)} {
351
+ Py_INCREF (self);
352
+ }
353
+ void operator ()(void *) {
354
+ gil_scoped_acquire gil;
355
+ Py_DECREF (self);
356
+ }
357
+ };
358
+
346
359
template <typename T>
347
360
struct smart_holder_type_caster_load {
348
361
using holder_type = pybindit::memory::smart_holder;
@@ -376,14 +389,6 @@ struct smart_holder_type_caster_load {
376
389
return *raw_ptr;
377
390
}
378
391
379
- struct shared_ptr_dec_ref_deleter {
380
- PyObject *self;
381
- void operator ()(void *) {
382
- gil_scoped_acquire gil;
383
- Py_DECREF (self);
384
- }
385
- };
386
-
387
392
std::shared_ptr<T> loaded_as_shared_ptr () const {
388
393
if (load_impl.unowned_void_ptr_from_direct_conversion != nullptr )
389
394
throw cast_error (" Unowned pointer from direct conversion cannot be converted to a"
@@ -404,24 +409,26 @@ struct smart_holder_type_caster_load {
404
409
std::shared_ptr<void > released_ptr = vptr_gd_ptr->released_ptr .lock ();
405
410
if (released_ptr)
406
411
return std::shared_ptr<T>(released_ptr, type_raw_ptr);
407
- auto self = reinterpret_cast <PyObject *>(load_impl. loaded_v_h . inst );
408
- Py_INCREF (self);
409
- std::shared_ptr<T> to_be_released (type_raw_ptr, shared_ptr_dec_ref_deleter{self} );
412
+ std::shared_ptr<T> to_be_released (
413
+ type_raw_ptr,
414
+ shared_ptr_trampoline_self_life_support (load_impl. loaded_v_h . inst ) );
410
415
vptr_gd_ptr->released_ptr = to_be_released;
411
416
return to_be_released;
412
417
}
413
- if (std::get_deleter<shared_ptr_dec_ref_deleter>(hld.vptr ) != nullptr ) {
418
+ auto sptsls_ptr = std::get_deleter<shared_ptr_trampoline_self_life_support>(hld.vptr );
419
+ if (sptsls_ptr != nullptr ) {
414
420
// This code is reachable only if there are multiple registered_instances for the
415
421
// same pointee.
416
- // SMART_HOLDER_WIP: keep weak_ref
417
- std::shared_ptr<void > void_shd_ptr = hld.template as_shared_ptr <void >();
418
- return std::shared_ptr<T>(void_shd_ptr, type_raw_ptr);
422
+ assert (reinterpret_cast <PyObject *>(load_impl.loaded_v_h .inst )
423
+ != sptsls_ptr->self );
424
+ return std::shared_ptr<T>(
425
+ type_raw_ptr,
426
+ shared_ptr_trampoline_self_life_support (load_impl.loaded_v_h .inst ));
419
427
}
420
428
if (!pybindit::memory::type_has_shared_from_this (type_raw_ptr)) {
421
- // SMART_HOLDER_WIP: keep weak_ref
422
- auto self = reinterpret_cast <PyObject *>(load_impl.loaded_v_h .inst );
423
- Py_INCREF (self);
424
- return std::shared_ptr<T>(type_raw_ptr, shared_ptr_dec_ref_deleter{self});
429
+ return std::shared_ptr<T>(
430
+ type_raw_ptr,
431
+ shared_ptr_trampoline_self_life_support (load_impl.loaded_v_h .inst ));
425
432
}
426
433
if (hld.vptr_is_external_shared_ptr ) {
427
434
pybind11_fail (" smart_holder_type_casters loaded_as_shared_ptr failure: not "
0 commit comments