@@ -38,10 +38,8 @@ High-level aspects:
38
38
* If created from an external `shared_ptr`, or a `unique_ptr` with a custom
39
39
deleter, including life-time management for external objects is infeasible.
40
40
41
- * The smart_holder is movable but not copyable, as a consequence of using
42
- unique_ptr for the vptr_deleter_armed_flag_ptr. Note that the bool for
43
- the flag has to live on the heap, for the smart_holder to be movable.
44
- unique_ptr is a great fit for this situation.
41
+ * By choice, the smart_holder is movable but not copyable, to keep the design
42
+ simple, and to guard against accidental copying overhead.
45
43
*/
46
44
47
45
#pragma once
@@ -60,8 +58,9 @@ namespace memory {
60
58
61
59
template <typename T>
62
60
struct guarded_builtin_delete {
63
- bool *flag_ptr;
64
- explicit guarded_builtin_delete (bool *armed_flag_ptr) : flag_ptr{armed_flag_ptr} {}
61
+ std::shared_ptr<bool > flag_ptr;
62
+ explicit guarded_builtin_delete (std::shared_ptr<bool > armed_flag_ptr)
63
+ : flag_ptr{armed_flag_ptr} {}
65
64
template <typename T_ = T,
66
65
typename std::enable_if<std::is_destructible<T_>::value, int >::type = 0 >
67
66
void operator ()(T *raw_ptr) {
@@ -80,8 +79,9 @@ struct guarded_builtin_delete {
80
79
81
80
template <typename T, typename D>
82
81
struct guarded_custom_deleter {
83
- bool *flag_ptr;
84
- explicit guarded_custom_deleter (bool *armed_flag_ptr) : flag_ptr{armed_flag_ptr} {}
82
+ std::shared_ptr<bool > flag_ptr;
83
+ explicit guarded_custom_deleter (std::shared_ptr<bool > armed_flag_ptr)
84
+ : flag_ptr{armed_flag_ptr} {}
85
85
void operator ()(T *raw_ptr) {
86
86
if (*flag_ptr)
87
87
D ()(raw_ptr);
@@ -96,13 +96,19 @@ inline bool is_std_default_delete(const std::type_info &rtti_deleter) {
96
96
97
97
struct smart_holder {
98
98
const std::type_info *rtti_uqp_del;
99
- std::unique_ptr <bool > vptr_deleter_armed_flag_ptr;
99
+ std::shared_ptr <bool > vptr_deleter_armed_flag_ptr;
100
100
std::shared_ptr<void > vptr;
101
101
bool vptr_is_using_noop_deleter : 1 ;
102
102
bool vptr_is_using_builtin_delete : 1 ;
103
103
bool vptr_is_external_shared_ptr : 1 ;
104
104
bool is_populated : 1 ;
105
105
106
+ // Design choice: smart_holder is movable but not copyable.
107
+ smart_holder (smart_holder &&) = default ;
108
+ smart_holder (const smart_holder &) = delete ;
109
+ smart_holder &operator =(smart_holder &&) = default ;
110
+ smart_holder &operator =(const smart_holder &) = delete ;
111
+
106
112
smart_holder ()
107
113
: rtti_uqp_del{nullptr }, vptr_is_using_noop_deleter{false },
108
114
vptr_is_using_builtin_delete{false }, vptr_is_external_shared_ptr{false }, is_populated{
@@ -182,7 +188,7 @@ struct smart_holder {
182
188
template <typename T>
183
189
static smart_holder from_raw_ptr_unowned (T *raw_ptr) {
184
190
smart_holder hld (false );
185
- hld.vptr .reset (raw_ptr, guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr . get () ));
191
+ hld.vptr .reset (raw_ptr, guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr ));
186
192
hld.vptr_is_using_noop_deleter = true ;
187
193
hld.is_populated = true ;
188
194
return hld;
@@ -213,7 +219,7 @@ struct smart_holder {
213
219
static smart_holder from_raw_ptr_take_ownership (T *raw_ptr) {
214
220
ensure_pointee_is_destructible<T>(" from_raw_ptr_take_ownership" );
215
221
smart_holder hld (true );
216
- hld.vptr .reset (raw_ptr, guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr . get () ));
222
+ hld.vptr .reset (raw_ptr, guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr ));
217
223
hld.vptr_is_using_builtin_delete = true ;
218
224
hld.is_populated = true ;
219
225
return hld;
@@ -246,10 +252,10 @@ struct smart_holder {
246
252
hld.vptr_is_using_builtin_delete = is_std_default_delete<T>(*hld.rtti_uqp_del );
247
253
if (hld.vptr_is_using_builtin_delete ) {
248
254
hld.vptr .reset (unq_ptr.get (),
249
- guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr . get () ));
255
+ guarded_builtin_delete<T>(hld.vptr_deleter_armed_flag_ptr ));
250
256
} else {
251
257
hld.vptr .reset (unq_ptr.get (),
252
- guarded_custom_deleter<T, D>(hld.vptr_deleter_armed_flag_ptr . get () ));
258
+ guarded_custom_deleter<T, D>(hld.vptr_deleter_armed_flag_ptr ));
253
259
}
254
260
unq_ptr.release ();
255
261
hld.is_populated = true ;
0 commit comments