@@ -110,10 +110,11 @@ class observable_unique_ptr_base {
110110 }
111111
112112 // / Fill in the observer pointer for objects inheriting from enable_observer_from_this.
113- void set_this_observer () noexcept {
113+ void set_this_observer_ () noexcept {
114114 if constexpr (std::is_base_of_v<enable_observer_from_this<T>, T>) {
115115 if (ptr_deleter.data ) {
116- ptr_deleter.data ->this_observer = *this ;
116+ ptr_deleter.data ->this_observer .set_data_ (block, ptr_deleter.data );
117+ ++block->refcount ;
117118 }
118119 }
119120 }
@@ -124,9 +125,7 @@ class observable_unique_ptr_base {
124125 * \note This is used by make_observable_unique().
125126 */
126127 observable_unique_ptr_base (control_block_type* ctrl, T* value) noexcept :
127- block (ctrl), ptr_deleter{Deleter{}, value} {
128- set_this_observer ();
129- }
128+ block (ctrl), ptr_deleter{Deleter{}, value} {}
130129
131130 // / Private constructor using pre-allocated control block.
132131 /* * \param ctrl The control block pointer
@@ -135,9 +134,7 @@ class observable_unique_ptr_base {
135134 * \note This is used by make_observable_sealed().
136135 */
137136 observable_unique_ptr_base (control_block_type* ctrl, T* value, Deleter del) noexcept :
138- block (ctrl), ptr_deleter{std::move (del), value} {
139- set_this_observer ();
140- }
137+ block (ctrl), ptr_deleter{std::move (del), value} {}
141138
142139 // Friendship is required for conversions.
143140 template <typename U>
@@ -197,7 +194,6 @@ class observable_unique_ptr_base {
197194 observable_unique_ptr_base (value.block, value.ptr_deleter.data, std::move(value.ptr_deleter)) {
198195 value.block = nullptr ;
199196 value.ptr_deleter .data = nullptr ;
200- set_this_observer ();
201197 }
202198
203199 // / Transfer ownership by implicit casting
@@ -212,7 +208,6 @@ class observable_unique_ptr_base {
212208 observable_unique_ptr_base (value.block, value.ptr_deleter.data, std::move(value.ptr_deleter)) {
213209 value.block = nullptr ;
214210 value.ptr_deleter .data = nullptr ;
215- set_this_observer ();
216211 }
217212
218213 // / Transfer ownership by explicit casting
@@ -227,7 +222,6 @@ class observable_unique_ptr_base {
227222 observable_unique_ptr_base (manager.block, value) {
228223 manager.block = nullptr ;
229224 manager.ptr_deleter .data = nullptr ;
230- set_this_observer ();
231225 }
232226
233227 // / Transfer ownership by explicit casting
@@ -242,7 +236,6 @@ class observable_unique_ptr_base {
242236 observable_unique_ptr_base (manager.block, value, std::move(del)) {
243237 manager.block = nullptr ;
244238 manager.ptr_deleter .data = nullptr ;
245- set_this_observer ();
246239 }
247240
248241 // / Transfer ownership by implicit casting
@@ -260,7 +253,6 @@ class observable_unique_ptr_base {
260253 ptr_deleter.data = value.ptr_deleter .data ;
261254 value.ptr_deleter .data = nullptr ;
262255 static_cast <Deleter&>(ptr_deleter) = std::move (static_cast <Deleter&>(value.ptr_deleter ));
263- set_this_observer ();
264256
265257 return *this ;
266258 }
@@ -283,7 +275,6 @@ class observable_unique_ptr_base {
283275 ptr_deleter.data = value.ptr_deleter .data ;
284276 value.ptr_deleter .data = nullptr ;
285277 static_cast <Deleter&>(ptr_deleter) = std::move (static_cast <Deleter&>(ptr_deleter));
286- set_this_observer ();
287278
288279 return *this ;
289280 }
@@ -321,8 +312,6 @@ class observable_unique_ptr_base {
321312 using std::swap;
322313 swap (block, other.block );
323314 swap (ptr_deleter, other.ptr_deleter );
324- other.set_this_observer ();
325- set_this_observer ();
326315 }
327316
328317 // / Replaces the managed object with a null pointer.
@@ -409,21 +398,6 @@ class observable_unique_ptr :
409398 return new control_block_type;
410399 }
411400
412- static void pop_ref_ (control_block_type* block) noexcept {
413- --block->refcount ;
414- if (block->refcount == 0 ) {
415- delete block;
416- }
417- }
418-
419- static void delete_and_pop_ref_ (control_block_type* block, T* data, Deleter& deleter) noexcept {
420- deleter (data);
421-
422- block->set_expired ();
423-
424- pop_ref_ (block);
425- }
426-
427401 // Friendship is required for conversions.
428402 template <typename U>
429403 friend class observer_ptr ;
@@ -461,7 +435,9 @@ class observable_unique_ptr :
461435 * using make_observable_unique() instead of this constructor.
462436 */
463437 explicit observable_unique_ptr (T* value) :
464- base(value != nullptr ? allocate_block_() : nullptr, value) {}
438+ base(value != nullptr ? allocate_block_() : nullptr, value) {
439+ base::set_this_observer_ ();
440+ }
465441
466442 // / Explicit ownership capture of a raw pointer, with customer deleter.
467443 /* * \param value The raw pointer to take ownership of
@@ -471,7 +447,9 @@ class observable_unique_ptr :
471447 * using make_observable_unique() instead of this constructor.
472448 */
473449 explicit observable_unique_ptr (T* value, Deleter del) :
474- base(value != nullptr ? allocate_block_() : nullptr, value, std::move(del)) {}
450+ base(value != nullptr ? allocate_block_() : nullptr, value, std::move(del)) {
451+ base::set_this_observer_ ();
452+ }
475453
476454 // / Transfer ownership by implicit casting
477455 /* * \param value The pointer to take ownership from
@@ -502,7 +480,9 @@ class observable_unique_ptr :
502480 */
503481 template <typename U, typename D>
504482 observable_unique_ptr (observable_unique_ptr<U,D>&& manager, T* value) noexcept :
505- base (std::move(manager), value) {}
483+ base (std::move(manager), value) {
484+ base::set_this_observer_ ();
485+ }
506486
507487 // / Transfer ownership by explicit casting
508488 /* * \param manager The smart pointer to take ownership from
@@ -513,7 +493,9 @@ class observable_unique_ptr :
513493 */
514494 template <typename U, typename D>
515495 observable_unique_ptr (observable_unique_ptr<U,D>&& manager, T* value, Deleter del) noexcept :
516- base (std::move(manager), value, del) {}
496+ base (std::move(manager), value, del) {
497+ base::set_this_observer_ ();
498+ }
517499
518500 // / Transfer ownership by implicit casting
519501 /* * \param value The pointer to take ownership from
@@ -572,8 +554,10 @@ class observable_unique_ptr :
572554 // Delete the old pointer
573555 // (this follows std::unique_ptr specs)
574556 if (old_ptr) {
575- delete_and_pop_ref_ (old_block, old_ptr, base::ptr_deleter);
557+ base:: delete_and_pop_ref_ (old_block, old_ptr, base::ptr_deleter);
576558 }
559+
560+ base::set_this_observer_ ();
577561 }
578562
579563 // / Releases ownership of the managed object and mark observers as expired.
@@ -636,7 +620,9 @@ class observable_sealed_ptr :
636620 * \note This is used by make_observable_sealed().
637621 */
638622 observable_sealed_ptr (control_block_type* ctrl, T* value) noexcept :
639- base (ctrl, value, oup::placement_delete<T>{}) {}
623+ base (ctrl, value, oup::placement_delete<T>{}) {
624+ base::set_this_observer_ ();
625+ }
640626
641627 // Friendship is required for conversions.
642628 template <typename U>
@@ -863,6 +849,9 @@ class observer_ptr {
863849 // Friendship is required for conversions.
864850 template <typename U>
865851 friend class observer_ptr ;
852+ // Friendship is required for enable_observer_from_this.
853+ template <typename U, typename D>
854+ friend class details ::observable_unique_ptr_base;
866855
867856 using control_block = details::control_block;
868857
@@ -876,6 +865,15 @@ class observer_ptr {
876865 }
877866 }
878867
868+ void set_data_ (control_block* b, T* d) noexcept {
869+ if (data) {
870+ pop_ref_ ();
871+ }
872+
873+ block = b;
874+ data = d;
875+ }
876+
879877public:
880878 // / Type of the pointed object
881879 using element_type = T;
@@ -964,12 +962,8 @@ class observer_ptr {
964962 */
965963 template <typename U, typename D, typename enable = std::enable_if_t <std::is_convertible_v<U*, T*>>>
966964 observer_ptr& operator =(const observable_unique_ptr<U,D>& owner) noexcept {
967- if (data) {
968- pop_ref_ ();
969- }
965+ set_data_ (owner.block , owner.ptr_deleter .data );
970966
971- block = owner.block ;
972- data = owner.ptr_deleter .data ;
973967 if (block) {
974968 ++block->refcount ;
975969 }
@@ -984,12 +978,8 @@ class observer_ptr {
984978 */
985979 template <typename U, typename enable = std::enable_if_t <std::is_convertible_v<U*, T*>>>
986980 observer_ptr& operator =(const observable_sealed_ptr<U>& owner) noexcept {
987- if (data) {
988- pop_ref_ ();
989- }
981+ set_data_ (owner.block , owner.ptr_deleter .data );
990982
991- block = owner.block ;
992- data = owner.ptr_deleter .data ;
993983 if (block) {
994984 ++block->refcount ;
995985 }
@@ -1005,12 +995,8 @@ class observer_ptr {
1005995 return *this ;
1006996 }
1007997
1008- if (data) {
1009- pop_ref_ ();
1010- }
998+ set_data_ (value.block , value.data );
1011999
1012- block = value.block ;
1013- data = value.data ;
10141000 if (block) {
10151001 ++block->refcount ;
10161002 }
@@ -1029,12 +1015,8 @@ class observer_ptr {
10291015 return *this ;
10301016 }
10311017
1032- if (data) {
1033- pop_ref_ ();
1034- }
1018+ set_data_ (value.block , value.data );
10351019
1036- block = value.block ;
1037- data = value.data ;
10381020 if (block) {
10391021 ++block->refcount ;
10401022 }
@@ -1048,13 +1030,9 @@ class observer_ptr {
10481030 * pointer is set to null and looses ownership.
10491031 */
10501032 observer_ptr& operator =(observer_ptr&& value) noexcept {
1051- if (data) {
1052- pop_ref_ ();
1053- }
1033+ set_data_ (value.block , value.data );
10541034
1055- block = value.block ;
10561035 value.block = nullptr ;
1057- data = value.data ;
10581036 value.data = nullptr ;
10591037
10601038 return *this ;
@@ -1069,13 +1047,9 @@ class observer_ptr {
10691047 */
10701048 template <typename U, typename enable = std::enable_if_t <std::is_convertible_v<U*, T*>>>
10711049 observer_ptr& operator =(observer_ptr<U>&& value) noexcept {
1072- if (data) {
1073- pop_ref_ ();
1074- }
1050+ set_data_ (value.block , value.data );
10751051
1076- block = value.block ;
10771052 value.block = nullptr ;
1078- data = value.data ;
10791053 value.data = nullptr ;
10801054
10811055 return *this ;
@@ -1207,11 +1181,11 @@ bool operator!= (const observer_ptr<T>& first, const observer_ptr<U>& second) no
12071181*/
12081182template <typename T>
12091183class enable_observer_from_this {
1210- observer_ptr<T> this_observer;
1184+ mutable observer_ptr<T> this_observer;
12111185
12121186 // Friendship is required for assignement of the observer.
12131187 template <typename U, typename D>
1214- friend class observable_unique_ptr_base ;
1188+ friend class details :: observable_unique_ptr_base;
12151189
12161190protected:
12171191 enable_observer_from_this () noexcept = default ;
0 commit comments