@@ -56,33 +56,14 @@ High-level aspects:
56
56
namespace pybindit {
57
57
namespace memory {
58
58
59
- struct guarded_operator_call {
59
+ struct guarded_delete {
60
+ void (*del_ptr)(void *);
60
61
bool armed_flag;
61
- explicit guarded_operator_call (bool armed_flag) : armed_flag{armed_flag} {}
62
- virtual void operator ()(void *) = 0;
63
- virtual ~guarded_operator_call () = default ;
64
-
65
- // Some compilers complain if the implicitly defined copy constructor is used.
66
- guarded_operator_call (const guarded_operator_call &) = default ;
67
- };
68
-
69
- template <typename T>
70
- struct guarded_builtin_delete : guarded_operator_call {
71
- explicit guarded_builtin_delete (bool armed_flag) : guarded_operator_call{armed_flag} {}
72
- void operator ()(void *raw_ptr) override { delete_impl<T>(raw_ptr); }
73
- template <typename T_ = T,
74
- typename std::enable_if<std::is_destructible<T_>::value, int >::type = 0 >
75
- void delete_impl (void *raw_ptr) {
62
+ guarded_delete (void (*del_ptr)(void *), bool armed_flag)
63
+ : del_ptr{del_ptr}, armed_flag{armed_flag} {}
64
+ void operator ()(void *raw_ptr) const {
76
65
if (armed_flag)
77
- delete (T *) raw_ptr;
78
- }
79
- template <typename T_ = T,
80
- typename std::enable_if<!std::is_destructible<T_>::value, int >::type = 0 >
81
- void delete_impl (void *) {
82
- // This noop operator is needed to avoid a compilation error (for `delete raw_ptr;`), but
83
- // throwing an exception from here could std::terminate the process. Therefore the runtime
84
- // check for lifetime-management correctness is implemented elsewhere (in
85
- // ensure_pointee_is_destructible()).
66
+ (*del_ptr)(raw_ptr);
86
67
}
87
68
};
88
69
@@ -105,12 +86,13 @@ guarded_delete make_guarded_builtin_delete(bool armed_flag) {
105
86
}
106
87
107
88
template <typename T, typename D>
108
- struct guarded_custom_deleter : guarded_operator_call {
109
- explicit guarded_custom_deleter (bool armed_flag) : guarded_operator_call{armed_flag} {}
110
- void operator ()(void *raw_ptr) override {
111
- if (armed_flag)
112
- D ()((T *) raw_ptr);
113
- }
89
+ inline void custom_delete (void *raw_ptr) {
90
+ D ()((T *) raw_ptr);
91
+ }
92
+
93
+ template <typename T, typename D>
94
+ guarded_delete make_guarded_custom_deleter (bool armed_flag) {
95
+ return guarded_delete (custom_delete<T, D>, armed_flag);
114
96
};
115
97
116
98
template <typename T>
@@ -121,7 +103,6 @@ inline bool is_std_default_delete(const std::type_info &rtti_deleter) {
121
103
122
104
struct smart_holder {
123
105
const std::type_info *rtti_uqp_del = nullptr ;
124
- guarded_operator_call *vptr_del = nullptr ;
125
106
std::shared_ptr<void > vptr;
126
107
bool vptr_is_using_noop_deleter : 1 ;
127
108
bool vptr_is_using_builtin_delete : 1 ;
@@ -213,25 +194,20 @@ struct smart_holder {
213
194
}
214
195
}
215
196
216
- template <typename T, typename D>
217
- void vptr_reset (T *raw_ptr, const D &del) {
218
- vptr.reset (raw_ptr, del); // Copies del.
219
- // The const_cast is only for certain compilers (Ubuntu 20 GCC 6.3.0 being one).
220
- vptr_del = const_cast <D *>(std::get_deleter<D>(vptr)); // Pointer to copy of del.
221
- }
222
-
223
197
void reset_vptr_deleter_armed_flag (bool armed_flag) const {
224
- if (vptr_del == nullptr ) {
198
+ // The const_cast is only for certain compilers (Ubuntu 20 GCC 6.3.0 being one).
199
+ auto vptr_del_ptr = const_cast <guarded_delete *>(std::get_deleter<guarded_delete>(vptr));
200
+ if (vptr_del_ptr == nullptr ) {
225
201
throw std::runtime_error (
226
202
" smart_holder::reset_vptr_deleter_armed_flag() called in an invalid context." );
227
203
}
228
- vptr_del ->armed_flag = armed_flag;
204
+ vptr_del_ptr ->armed_flag = armed_flag;
229
205
}
230
206
231
207
template <typename T>
232
208
static smart_holder from_raw_ptr_unowned (T *raw_ptr) {
233
209
smart_holder hld;
234
- hld.vptr_reset (raw_ptr, guarded_builtin_delete<T>( false ) );
210
+ hld.vptr . reset (raw_ptr, []( void *) {} );
235
211
hld.vptr_is_using_noop_deleter = true ;
236
212
hld.is_populated = true ;
237
213
return hld;
@@ -262,7 +238,7 @@ struct smart_holder {
262
238
static smart_holder from_raw_ptr_take_ownership (T *raw_ptr) {
263
239
ensure_pointee_is_destructible<T>(" from_raw_ptr_take_ownership" );
264
240
smart_holder hld;
265
- hld.vptr_reset (raw_ptr, guarded_builtin_delete <T>(true ));
241
+ hld.vptr . reset (raw_ptr, make_guarded_builtin_delete <T>(true ));
266
242
hld.vptr_is_using_builtin_delete = true ;
267
243
hld.is_populated = true ;
268
244
return hld;
@@ -281,10 +257,7 @@ struct smart_holder {
281
257
}
282
258
283
259
// Caller is responsible for ensuring preconditions (SMART_HOLDER_WIP: details).
284
- void release_disowned () {
285
- vptr.reset ();
286
- vptr_del = nullptr ;
287
- }
260
+ void release_disowned () { vptr.reset (); }
288
261
289
262
// SMART_HOLDER_WIP: review this function.
290
263
void ensure_can_release_ownership (const char *context = " ensure_can_release_ownership" ) const {
@@ -313,9 +286,10 @@ struct smart_holder {
313
286
hld.rtti_uqp_del = &typeid (D);
314
287
hld.vptr_is_using_builtin_delete = is_std_default_delete<T>(*hld.rtti_uqp_del );
315
288
if (hld.vptr_is_using_builtin_delete ) {
316
- hld.vptr_reset (unq_ptr.get (), guarded_builtin_delete <T>(true ));
289
+ hld.vptr . reset (unq_ptr.get (), make_guarded_builtin_delete <T>(true ));
317
290
} else {
318
- hld.vptr_reset (unq_ptr.get (), guarded_custom_deleter<T, D>(true ));
291
+ make_guarded_custom_deleter<T, D>(false );
292
+ hld.vptr .reset (unq_ptr.get (), make_guarded_custom_deleter<T, D>(true ));
319
293
}
320
294
unq_ptr.release ();
321
295
hld.is_populated = true ;
0 commit comments