Skip to content

Commit 362e64e

Browse files
committed
WIP snapshot: replacing std::shared_ptr<bool> flag_ptr with simple bool armed_flag.
1 parent 459301d commit 362e64e

File tree

1 file changed

+28
-21
lines changed

1 file changed

+28
-21
lines changed

include/pybind11/detail/smart_holder_poc.h

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,26 +57,24 @@ namespace pybindit {
5757
namespace memory {
5858

5959
struct guarded_operator_call {
60-
std::shared_ptr<bool> flag_ptr;
61-
explicit guarded_operator_call(std::shared_ptr<bool> armed_flag_ptr)
62-
: flag_ptr{armed_flag_ptr} {}
60+
bool armed_flag;
61+
explicit guarded_operator_call(bool armed_flag) : armed_flag{armed_flag} {}
6362
virtual void operator()(void *) = 0;
6463
virtual ~guarded_operator_call() = default;
6564
guarded_operator_call(guarded_operator_call &&) = default;
66-
guarded_operator_call(guarded_operator_call &) = delete;
65+
guarded_operator_call(guarded_operator_call &) = default;
6766
guarded_operator_call &operator=(guarded_operator_call &&) = delete;
6867
guarded_operator_call &operator=(const guarded_operator_call &) = delete;
6968
};
7069

7170
template <typename T>
7271
struct guarded_builtin_delete : guarded_operator_call {
73-
explicit guarded_builtin_delete(std::shared_ptr<bool> armed_flag_ptr)
74-
: guarded_operator_call(armed_flag_ptr) {}
72+
explicit guarded_builtin_delete(bool armed_flag) : guarded_operator_call{armed_flag} {}
7573
void operator()(void *raw_ptr) override { delete_impl<T>(raw_ptr); }
7674
template <typename T_ = T,
7775
typename std::enable_if<std::is_destructible<T_>::value, int>::type = 0>
7876
void delete_impl(void *raw_ptr) {
79-
if (*flag_ptr)
77+
if (armed_flag)
8078
delete (T *) raw_ptr;
8179
}
8280
template <typename T_ = T,
@@ -109,10 +107,9 @@ guarded_delete make_guarded_builtin_delete(bool armed_flag) {
109107

110108
template <typename T, typename D>
111109
struct guarded_custom_deleter : guarded_operator_call {
112-
explicit guarded_custom_deleter(std::shared_ptr<bool> armed_flag_ptr)
113-
: guarded_operator_call(armed_flag_ptr) {}
110+
explicit guarded_custom_deleter(bool armed_flag) : guarded_operator_call{armed_flag} {}
114111
virtual void operator()(void *raw_ptr) override {
115-
if (*flag_ptr)
112+
if (armed_flag)
116113
D()((T *) raw_ptr);
117114
}
118115
};
@@ -125,6 +122,7 @@ inline bool is_std_default_delete(const std::type_info &rtti_deleter) {
125122

126123
struct smart_holder {
127124
const std::type_info *rtti_uqp_del = nullptr;
125+
guarded_operator_call *vptr_del = nullptr;
128126
std::shared_ptr<void> vptr;
129127
bool vptr_is_using_noop_deleter : 1;
130128
bool vptr_is_using_builtin_delete : 1;
@@ -228,7 +226,8 @@ struct smart_holder {
228226
template <typename T>
229227
static smart_holder from_raw_ptr_unowned(T *raw_ptr) {
230228
smart_holder hld;
231-
hld.vptr.reset(raw_ptr, [](void *) {});
229+
hld.vptr.reset(raw_ptr, guarded_builtin_delete<T>(false));
230+
hld.vptr_del = std::get_deleter<guarded_builtin_delete<T>>(hld.vptr);
232231
hld.vptr_is_using_noop_deleter = true;
233232
hld.is_populated = true;
234233
return hld;
@@ -259,12 +258,21 @@ struct smart_holder {
259258
static smart_holder from_raw_ptr_take_ownership(T *raw_ptr) {
260259
ensure_pointee_is_destructible<T>("from_raw_ptr_take_ownership");
261260
smart_holder hld;
262-
hld.vptr.reset(raw_ptr, make_guarded_builtin_delete<T>(true));
261+
hld.vptr.reset(raw_ptr, guarded_builtin_delete<T>(true));
262+
hld.vptr_del = std::get_deleter<guarded_builtin_delete<T>>(hld.vptr);
263263
hld.vptr_is_using_builtin_delete = true;
264264
hld.is_populated = true;
265265
return hld;
266266
}
267267

268+
void reset_vptr_deleter_armed_flag(bool armed_flag) {
269+
if (vptr_del == nullptr) {
270+
throw std::runtime_error(
271+
"smart_holder::reset_vptr_deleter_armed_flag() called in an invalid context.");
272+
}
273+
vptr_del->armed_flag = armed_flag;
274+
}
275+
268276
// Caller is responsible for ensuring preconditions (SMART_HOLDER_WIP: details).
269277
void disown() {
270278
reset_vptr_deleter_armed_flag(false);
@@ -278,7 +286,10 @@ struct smart_holder {
278286
}
279287

280288
// Caller is responsible for ensuring preconditions (SMART_HOLDER_WIP: details).
281-
void release_disowned() { vptr.reset(); }
289+
void release_disowned() {
290+
vptr.reset();
291+
vptr_del = nullptr;
292+
}
282293

283294
// SMART_HOLDER_WIP: review this function.
284295
void ensure_can_release_ownership(const char *context = "ensure_can_release_ownership") const {
@@ -306,17 +317,13 @@ struct smart_holder {
306317
smart_holder hld;
307318
hld.rtti_uqp_del = &typeid(D);
308319
hld.vptr_is_using_builtin_delete = is_std_default_delete<T>(*hld.rtti_uqp_del);
309-
guarded_operator_call *vptr_del = nullptr;
310320
if (hld.vptr_is_using_builtin_delete) {
311-
hld.vptr.reset(unq_ptr.get(),
312-
guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr));
313-
vptr_del = std::get_deleter<guarded_builtin_delete<T>>(hld.vptr);
321+
hld.vptr.reset(unq_ptr.get(), guarded_builtin_delete<T>(true));
322+
hld.vptr_del = std::get_deleter<guarded_builtin_delete<T>>(hld.vptr);
314323
} else {
315-
hld.vptr.reset(unq_ptr.get(),
316-
guarded_custom_deleter<T, D>(hld.vptr_deleter_armed_flag_ptr));
317-
vptr_del = std::get_deleter<guarded_custom_deleter<T, D>>(hld.vptr);
324+
hld.vptr.reset(unq_ptr.get(), guarded_custom_deleter<T, D>(true));
325+
hld.vptr_del = std::get_deleter<guarded_custom_deleter<T, D>>(hld.vptr);
318326
}
319-
assert(vptr_del != nullptr);
320327
unq_ptr.release();
321328
hld.is_populated = true;
322329
return hld;

0 commit comments

Comments
 (0)