Stroika Library 3.0d23
 
Loading...
Searching...
No Matches
SharedByValue.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
6
7namespace Stroika::Foundation::Memory {
8
9 // DEPRECATED STUFF
10 template <typename T, typename SHARED_IMPL, typename COPIER>
11 [[deprecated ("Since Stroika v3.0d23 - not used - doesnt do anything")]] constexpr bool SharedByValue_IsCopier ()
12 {
13 // @todo should match API function<SHARED_IMPL(const T&)>
14 return true;
15 }
16 template <typename T, typename SHARED_IMPL = shared_ptr<T>, typename COPIER = SharedByValueSupport::DefaultValueCopier_FunctionObject<T, SHARED_IMPL>>
17 using SharedByValue_Traits [[deprecated ("Since Stroika v3.0d23 - use DefaultTraits directly")]] =
19
20 using SharedByValue_State [[deprecated ("Since Stroika v3.0d23 - use SharedByValueSupport::SharingState directly")]] =
22
23 /*
24 ********************************************************************************
25 *********** SharedByValueSupport::DefaultValueCopier<T,SHARED_IMPL> ************
26 ********************************************************************************
27 */
28 template <typename T, typename SHARED_IMPL>
30 {
31 if constexpr (same_as<SHARED_IMPL, shared_ptr<T>>) {
32 return Memory::MakeSharedPtr<T> (t); // more efficient
33 }
34 else {
35 return SHARED_IMPL{new T{t}};
36 }
37 }
38 template <typename T, typename SHARED_IMPL>
39#if __cplusplus >= kStrokia_Foundation_Common_cplusplus_23 || _HAS_CXX23 /*vis studio uses _HAS_CXX23 */
41#else
43#endif
44 {
45 return DefaultValueCopier (t);
46 }
47
48 /*
49 ********************************************************************************
50 *************************** SharedByValue<T, TRAITS> ***************************
51 ********************************************************************************
52 */
53#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
54 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
56 requires (not same_as<default_copier_type, MissingCopierTypeSentinel>)
57 : fSharedImpl_{}
58 {
59 if constexpr (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
60 fCopier_ = TRAITS::kDefaultCopier;
61 }
62 }
63 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
64 inline SharedByValue<T, TRAITS>::SharedByValue ([[maybe_unused]] nullptr_t) noexcept
65 requires (not same_as<default_copier_type, MissingCopierTypeSentinel>)
66 : fSharedImpl_{}
67 {
68 if constexpr (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
69 fCopier_ = TRAITS::kDefaultCopier;
70 }
71 }
72 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
73 inline SharedByValue<T, TRAITS>::SharedByValue (const shared_ptr_type& from) noexcept
74 requires (not same_as<default_copier_type, MissingCopierTypeSentinel>)
75 : fSharedImpl_{from}
76 {
77 if constexpr (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
78 fCopier_ = TRAITS::kDefaultCopier;
79 }
80 }
81 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
82 inline SharedByValue<T, TRAITS>::SharedByValue (const element_type& from)
83 requires (not same_as<default_copier_type, MissingCopierTypeSentinel>)
84 : fSharedImpl_{TRAITS::kDefaultCopier (from)}
85 {
86 if constexpr (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
87 fCopier_ = TRAITS::kDefaultCopier;
88 }
89 }
90 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
91 inline SharedByValue<T, TRAITS>::SharedByValue (shared_ptr_type&& from) noexcept
92 requires (not same_as<default_copier_type, MissingCopierTypeSentinel>)
93 : fSharedImpl_{move (from)}
94 {
95 if constexpr (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
96 fCopier_ = TRAITS::kDefaultCopier;
97 }
98 }
99 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
100 inline SharedByValue<T, TRAITS>::SharedByValue (const shared_ptr_type& from, const instance_defined_copier_type& copier) noexcept
101 requires (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>)
102 : fCopier_{copier}
103 , fSharedImpl_{from}
104 {
105 }
106 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
107 inline SharedByValue<T, TRAITS>::SharedByValue (const element_type& from, const instance_defined_copier_type& copier)
108 requires (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>)
109 : fCopier_{copier}
110 , fSharedImpl_{copier (from)}
111 {
112 }
113 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
114 inline SharedByValue<T, TRAITS>::SharedByValue (shared_ptr_type&& from, const instance_defined_copier_type&& copier) noexcept
115 requires (not same_as<instance_defined_copier_type, MissingCopierTypeSentinel>)
116 : fCopier_{move (copier)}
117 , fSharedImpl_{move (from)}
118 {
119 }
120#endif
121 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
122 inline SharedByValue<T, TRAITS>& SharedByValue<T, TRAITS>::operator= (const shared_ptr_type& from) noexcept
123 {
124 // If the pointers are the same, there is no need to copy, as the reference counts must also be the same,
125 // and we can avoid the (common) and costly memory barrier
126 if (fSharedImpl_ != from) [[likely]] {
127 fSharedImpl_ = from;
128 }
129 return *this;
130 }
131 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
132 inline SharedByValue<T, TRAITS>::operator bool () const noexcept
133 {
134 return static_cast<bool> (fSharedImpl_);
135 }
136 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
137 inline SharedByValue<T, TRAITS>& SharedByValue<T, TRAITS>::operator= (shared_ptr_type&& from) noexcept
138 {
139 // If the pointers are the same, there is no need to copy, as the reference counts must also be the same,
140 // and we can avoid the (common) and costly memory barrier
141 if (fSharedImpl_ != from) [[likely]] {
142 fSharedImpl_ = move (from);
143 }
144 return *this;
145 }
146 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
147 inline const typename SharedByValue<T, TRAITS>::element_type* SharedByValue<T, TRAITS>::cget () const noexcept
148 {
149 return fSharedImpl_.get ();
150 }
151 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
152 inline auto SharedByValue<T, TRAITS>::cget_ptr () const -> shared_ptr_type
153 {
154 return fSharedImpl_;
155 }
156 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
157 inline auto SharedByValue<T, TRAITS>::rwget_ptr () -> shared_ptr_type
158 {
159 if constexpr (same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
160 return rwget_ptr (TRAITS::kDefaultCopier);
161 }
162 else {
163 return rwget_ptr (fCopier_);
164 }
165 }
166 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
167 template <typename COPIER>
168 auto SharedByValue<T, TRAITS>::rwget_ptr (COPIER&& copier) -> shared_ptr_type
169 {
170 if (fSharedImpl_ != nullptr) [[likely]] {
171 auto result = forward<COPIER> (copier) (fSharedImpl_);
172 Assert (result.use_count () == 1);
173 return result;
174 }
175 return nullptr;
176 }
177 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
178 inline auto SharedByValue<T, TRAITS>::rwget () -> element_type*
179 {
180 if constexpr (same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
181 return rwget (TRAITS::kDefaultCopier);
182 }
183 else {
184 return rwget (fCopier_);
185 }
186 }
187 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
188 template <typename COPIER>
189 inline auto SharedByValue<T, TRAITS>::rwget (COPIER&& copier) -> element_type*
190 {
191 /*
192 * Increment refCount before assureNReferences/breakreferencs so we can save
193 * the original shared_ptr and return it in case its needed (e.g. to update iterators).
194 *
195 * Save this way so no race (after Assure1Reference() other remaining ptr could go away.
196 */
197 if (fSharedImpl_ != nullptr) [[likely]] {
198 AssureNOrFewerReferences (forward<COPIER> (copier));
199 Ensure (fSharedImpl_.use_count () == 1);
200 return fSharedImpl_.get ();
201 }
202 return nullptr;
203 }
204 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
205 inline const typename SharedByValue<T, TRAITS>::element_type* SharedByValue<T, TRAITS>::operator->() const
206 {
207 return fSharedImpl_.get ();
208 }
209 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
210 inline typename SharedByValue<T, TRAITS>::element_type* SharedByValue<T, TRAITS>::operator->()
211 {
212 return rwget ();
213 }
214 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
215 inline const typename SharedByValue<T, TRAITS>::element_type& SharedByValue<T, TRAITS>::operator* () const
216 {
217 const element_type* ptr = cget ();
218 EnsureNotNull (ptr);
219 return *ptr;
220 }
221 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
222 constexpr bool SharedByValue<T, TRAITS>::operator== (nullptr_t) const
223 {
224 return fSharedImpl_ == nullptr;
225 }
226 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
227 inline auto SharedByValue<T, TRAITS>::GetElementCopier () const -> element_copier_type
228 {
229 if constexpr (same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
230 return TRAITS::kDefaultCopier;
231 }
232 else {
233 return fCopier_;
234 }
235 }
236 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
238 {
239 switch (fSharedImpl_.use_count ()) {
240 case 0:
241 Assert (fSharedImpl_.get () == nullptr);
242 return SharingState::eNull;
243 case 1:
244 Assert (fSharedImpl_.get () != nullptr);
245 return SharingState::eSolo;
246 default:
247 Assert (fSharedImpl_.get () != nullptr);
248 //NOT NECESSARILY - cuz there is no lock
249 // between the use_count and this unique call, so another object could decrement its count
250 // and this could be that it was shared, but is no solo.
251 // Assert (not fSharedImpl_.unique ());
252 // -- LGP 2015-01-10
253 return SharingState::eShared;
254 }
255 }
256 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
258 {
259 return fSharedImpl_.use_count () == 1;
260 }
261 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
262 inline unsigned int SharedByValue<T, TRAITS>::use_count () const
263 {
264 return fSharedImpl_.use_count ();
265 }
266 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
267 template <typename COPIER>
268 inline void SharedByValue<T, TRAITS>::AssureNOrFewerReferences (COPIER&& copier, unsigned int n)
269 {
270 Require (n != 0);
271 if (static_cast<unsigned int> (fSharedImpl_.use_count ()) > n) [[unlikely]] {
272 BreakReferences_ (forward<COPIER> (copier));
273 Assert (this->use_count () == 1);
274 }
275 }
276 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
277 inline void SharedByValue<T, TRAITS>::AssureNOrFewerReferences (unsigned int n)
278 {
279 if constexpr (same_as<instance_defined_copier_type, MissingCopierTypeSentinel>) {
280 AssureNOrFewerReferences (TRAITS::kDefaultCopier, n);
281 }
282 else {
283 AssureNOrFewerReferences (fCopier_, n);
284 }
285 }
286 template <typename T, SharedByValueSupport::ITraits<T> TRAITS>
287 template <typename COPIER>
288 void SharedByValue<T, TRAITS>::BreakReferences_ (COPIER&& copier)
289 {
290 RequireNotNull (fSharedImpl_);
291 /*
292 * For a valid pointer that is reference counted and multiply shared,
293 * make a copy of that pointer via our fCloner function, and assign
294 * that cloned reference to this.
295 *
296 * Note that by doing so, we remove any references to the current
297 * item, and end up with our having the sole reference to the new copy of fPtr.
298 *
299 * Since we will be cloning the given pointer, we assume(assert) that
300 * it is non-nullptr.
301 */
302
303 // This is not NECESSARILY so. Another thread could have just released this pointer, in which case
304 // the creation of a new object was pointless, but harmless, as the assignemnt should decrement to zero the old
305 // value and it should go away.
306 //
307 // Actually, this gets triggered alot when used in heavily multithreaded applications, like
308 // Test10_MutlipleThreadsReadingOneUpdateUsingSynchronizedContainer_, so comment out the weak assert - just too noisy
309 // and really not a problem -- LGP 2021-11-06
310 //WeakAssert (not unique ());
311
312 fSharedImpl_ = forward<COPIER> (copier) (*fSharedImpl_); // make a new shared_ptr (clone) and assign-overwriting.
313
314 // this assignment requires overwriting THIS object, so must be externally synchronized. ASSERT EXTERNALLY SYNRCHONIZED HERE
315 // so treat this as real assertion erorr -- LGP 2021-10-15
316 Ensure (unique ());
317 }
318
319}
#define EnsureNotNull(p)
Definition Assertions.h:341
#define RequireNotNull(p)
Definition Assertions.h:348
SharedByValue is a utility class to implement Copy-On-Write (aka COW) - sort of halfway between uniqu...
nonvirtual unsigned int use_count() const
nonvirtual shared_ptr_type cget_ptr() const
access te underlying shared_ptr stored in the SharedByValue. This should be treated as readonly and o...
nonvirtual shared_ptr_type rwget_ptr()
forced copy of the underlying shared_ptr data
nonvirtual const element_type * cget() const noexcept
nonvirtual const element_type * operator->() const
nonvirtual void AssureNOrFewerReferences(COPIER &&copier, unsigned int n=1u)
nonvirtual SharingState GetSharingState() const
nonvirtual const element_type & operator*() const
DefaultTraits_NoInstanceCopier< T, COPIER_INSTANCE > DefaultTraits
DefaultTraits is a utility struct to provide parameterized support for SharedByValue<>
SHARED_IMPL DefaultValueCopier(const T &t)
DefaultValueCopier is the default value-copier for copying SharedByValue (thing that clones a shared_...
DefaultValueCopier_FunctionObject same as DefaultValueCopier, but as a function object.