Skip to content

Commit fb836cb

Browse files
committed
[skip ci] Only pass around memory::get_guarded_delete function pointer.
1 parent 14f60a0 commit fb836cb

5 files changed

Lines changed: 31 additions & 29 deletions

File tree

include/pybind11/detail/internals.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
#include <atomic>
2020
#include <exception>
21-
#include <memory>
2221
#include <mutex>
2322
#include <thread>
2423

@@ -256,9 +255,7 @@ struct internals {
256255

257256
type_map<PyObject *> native_enum_type_map;
258257

259-
using get_memory_guarded_delete_fn
260-
= memory::guarded_delete *(*) (const std::shared_ptr<void> &);
261-
get_memory_guarded_delete_fn get_memory_guarded_delete = nullptr;
258+
memory::get_guarded_delete_fn get_memory_guarded_delete = memory::get_guarded_delete;
262259

263260
internals()
264261
: static_property_type(make_static_property_type()),
@@ -278,9 +275,6 @@ struct internals {
278275
instance_shards.reset(new instance_map_shard[num_shards]);
279276
instance_shards_mask = num_shards - 1;
280277
#endif
281-
get_memory_guarded_delete = [](const std::shared_ptr<void> &ptr) {
282-
return std::get_deleter<memory::guarded_delete>(ptr);
283-
};
284278
}
285279
internals(const internals &other) = delete;
286280
internals(internals &&other) = delete;

include/pybind11/detail/struct_smart_holder.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ struct guarded_delete {
100100
}
101101
};
102102

103+
inline guarded_delete *get_guarded_delete(const std::shared_ptr<void> &ptr) {
104+
return std::get_deleter<guarded_delete>(ptr);
105+
}
106+
107+
using get_guarded_delete_fn = guarded_delete *(*) (const std::shared_ptr<void> &);
108+
103109
template <typename T, typename std::enable_if<std::is_destructible<T>::value, int>::type = 0>
104110
inline void builtin_delete_if_destructible(void *raw_ptr) {
105111
std::default_delete<T>{}(static_cast<T *>(raw_ptr));
@@ -231,7 +237,8 @@ struct smart_holder {
231237
}
232238
}
233239

234-
void reset_vptr_deleter_armed_flag(guarded_delete *vptr_del_ptr, bool armed_flag) const {
240+
void reset_vptr_deleter_armed_flag(const get_guarded_delete_fn ggd_fn, bool armed_flag) const {
241+
auto *vptr_del_ptr = ggd_fn(vptr);
235242
if (vptr_del_ptr == nullptr) {
236243
throw std::runtime_error(
237244
"smart_holder::reset_vptr_deleter_armed_flag() called in an invalid context.");
@@ -241,7 +248,9 @@ struct smart_holder {
241248

242249
// Caller is responsible for precondition: ensure_compatible_rtti_uqp_del<T, D>() must succeed.
243250
template <typename T, typename D>
244-
std::unique_ptr<D> extract_deleter(const char *context, const guarded_delete *gd) const {
251+
std::unique_ptr<D> extract_deleter(const char *context,
252+
const get_guarded_delete_fn ggd_fn) const {
253+
auto *gd = ggd_fn(vptr);
245254
if (gd && gd->use_del_fun) {
246255
const auto &custom_deleter_ptr = gd->del_fun.template target<custom_deleter<T, D>>();
247256
if (custom_deleter_ptr == nullptr) {
@@ -286,15 +295,15 @@ struct smart_holder {
286295

287296
// Caller is responsible for ensuring the complex preconditions
288297
// (see `smart_holder_type_caster_support::load_helper`).
289-
void disown(guarded_delete *vptr_del_ptr) {
290-
reset_vptr_deleter_armed_flag(vptr_del_ptr, false);
298+
void disown(const get_guarded_delete_fn ggd_fn) {
299+
reset_vptr_deleter_armed_flag(ggd_fn, false);
291300
is_disowned = true;
292301
}
293302

294303
// Caller is responsible for ensuring the complex preconditions
295304
// (see `smart_holder_type_caster_support::load_helper`).
296-
void reclaim_disowned(guarded_delete *vptr_del_ptr) {
297-
reset_vptr_deleter_armed_flag(vptr_del_ptr, true);
305+
void reclaim_disowned(const get_guarded_delete_fn ggd_fn) {
306+
reset_vptr_deleter_armed_flag(ggd_fn, true);
298307
is_disowned = false;
299308
}
300309

@@ -310,8 +319,8 @@ struct smart_holder {
310319

311320
// Caller is responsible for ensuring the complex preconditions
312321
// (see `smart_holder_type_caster_support::load_helper`).
313-
void release_ownership(guarded_delete *vptr_del_ptr) {
314-
reset_vptr_deleter_armed_flag(vptr_del_ptr, false);
322+
void release_ownership(const get_guarded_delete_fn ggd_fn) {
323+
reset_vptr_deleter_armed_flag(ggd_fn, false);
315324
release_disowned();
316325
}
317326

include/pybind11/detail/type_caster_base.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ handle smart_holder_from_unique_ptr(std::unique_ptr<T, D> &&src,
576576
}
577577
// Critical transfer-of-ownership section. This must stay together.
578578
self_life_support->deactivate_life_support();
579-
holder.reclaim_disowned(get_internals().get_memory_guarded_delete(holder.vptr));
579+
holder.reclaim_disowned(get_internals().get_memory_guarded_delete);
580580
(void) src.release();
581581
// Critical section end.
582582
return existing_inst;
@@ -819,13 +819,13 @@ struct load_helper : value_and_holder_helper {
819819
assert(!python_instance_is_alias || self_life_support);
820820

821821
std::unique_ptr<D> extracted_deleter = holder().template extract_deleter<T, D>(
822-
context, get_internals().get_memory_guarded_delete(holder().vptr));
822+
context, get_internals().get_memory_guarded_delete);
823823

824824
// Critical transfer-of-ownership section. This must stay together.
825825
if (self_life_support != nullptr) {
826-
holder().disown(get_internals().get_memory_guarded_delete(holder().vptr));
826+
holder().disown(get_internals().get_memory_guarded_delete);
827827
} else {
828-
holder().release_ownership(get_internals().get_memory_guarded_delete(holder().vptr));
828+
holder().release_ownership(get_internals().get_memory_guarded_delete);
829829
}
830830
auto result = unique_with_deleter<T, D>(raw_type_ptr, std::move(extracted_deleter));
831831
if (self_life_support != nullptr) {
@@ -849,10 +849,9 @@ struct load_helper : value_and_holder_helper {
849849
return unique_with_deleter<T, D>(nullptr, std::unique_ptr<D>());
850850
}
851851
holder().template ensure_compatible_rtti_uqp_del<T, D>(context);
852-
return unique_with_deleter<T, D>(
853-
raw_type_ptr,
854-
std::move(holder().template extract_deleter<T, D>(
855-
context, get_internals().get_memory_guarded_delete(holder().vptr))));
852+
return unique_with_deleter<T, D>(raw_type_ptr,
853+
std::move(holder().template extract_deleter<T, D>(
854+
context, get_internals().get_memory_guarded_delete)));
856855
}
857856
};
858857

tests/pure_cpp/smart_holder_poc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ T *as_raw_ptr_release_ownership(smart_holder &hld,
3636
const char *context = "as_raw_ptr_release_ownership") {
3737
hld.ensure_can_release_ownership(context);
3838
T *raw_ptr = hld.as_raw_ptr_unowned<T>();
39-
hld.release_ownership(std::get_deleter<guarded_delete>(hld.vptr));
39+
hld.release_ownership(get_guarded_delete);
4040
return raw_ptr;
4141
}
4242

@@ -46,7 +46,7 @@ std::unique_ptr<T, D> as_unique_ptr(smart_holder &hld) {
4646
hld.ensure_compatible_rtti_uqp_del<T, D>(context);
4747
hld.ensure_use_count_1(context);
4848
T *raw_ptr = hld.as_raw_ptr_unowned<T>();
49-
hld.release_ownership(std::get_deleter<guarded_delete>(hld.vptr));
49+
hld.release_ownership(get_guarded_delete);
5050
// KNOWN DEFECT (see PR #4850): Does not copy the deleter.
5151
return std::unique_ptr<T, D>(raw_ptr);
5252
}

tests/pure_cpp/smart_holder_poc_test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,12 @@ TEST_CASE("from_raw_ptr_take_ownership+as_shared_ptr", "[S]") {
161161
TEST_CASE("from_raw_ptr_take_ownership+disown+reclaim_disowned", "[S]") {
162162
auto hld = smart_holder::from_raw_ptr_take_ownership(new int(19));
163163
std::unique_ptr<int> new_owner(hld.as_raw_ptr_unowned<int>());
164-
hld.disown(std::get_deleter<guarded_delete>(hld.vptr));
164+
hld.disown(pybind11::memory::get_guarded_delete);
165165
REQUIRE(poc::as_lvalue_ref<int>(hld) == 19);
166166
REQUIRE(*new_owner == 19);
167167
// Manually verified: without this, clang++ -fsanitize=address reports
168168
// "detected memory leaks".
169-
hld.reclaim_disowned(std::get_deleter<guarded_delete>(hld.vptr));
169+
hld.reclaim_disowned(pybind11::memory::get_guarded_delete);
170170
// NOLINTNEXTLINE(bugprone-unused-return-value)
171171
(void) new_owner.release(); // Manually verified: without this, clang++ -fsanitize=address
172172
// reports "attempting double-free".
@@ -177,7 +177,7 @@ TEST_CASE("from_raw_ptr_take_ownership+disown+reclaim_disowned", "[S]") {
177177
TEST_CASE("from_raw_ptr_take_ownership+disown+release_disowned", "[S]") {
178178
auto hld = smart_holder::from_raw_ptr_take_ownership(new int(19));
179179
std::unique_ptr<int> new_owner(hld.as_raw_ptr_unowned<int>());
180-
hld.disown(std::get_deleter<guarded_delete>(hld.vptr));
180+
hld.disown(pybind11::memory::get_guarded_delete);
181181
REQUIRE(poc::as_lvalue_ref<int>(hld) == 19);
182182
REQUIRE(*new_owner == 19);
183183
hld.release_disowned();
@@ -189,7 +189,7 @@ TEST_CASE("from_raw_ptr_take_ownership+disown+ensure_is_not_disowned", "[E]") {
189189
auto hld = smart_holder::from_raw_ptr_take_ownership(new int(19));
190190
hld.ensure_is_not_disowned(context); // Does not throw.
191191
std::unique_ptr<int> new_owner(hld.as_raw_ptr_unowned<int>());
192-
hld.disown(std::get_deleter<guarded_delete>(hld.vptr));
192+
hld.disown(pybind11::memory::get_guarded_delete);
193193
REQUIRE_THROWS_WITH(hld.ensure_is_not_disowned(context),
194194
"Holder was disowned already (test_case).");
195195
}

0 commit comments

Comments
 (0)