169#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_SMART_PTR_POLICIES_H
170#define LASS_GUARDIAN_OF_INCLUSION_UTIL_SMART_PTR_POLICIES_H
195 typename Cascade = meta::EmptyType
197class ObjectStorage:
public Cascade
201 typedef ObjectStorage<T, Cascade> TSelf;
204 typedef T& TReference;
206 TStorage& storage() {
return storage_; }
207 const TStorage& storage()
const {
return storage_; }
211 ObjectStorage(): Cascade(), storage_(defaultStorage()) {}
212 explicit ObjectStorage(T* pointee): Cascade(), storage_(pointee) {}
213 ObjectStorage(
const TSelf& other): Cascade(other), storage_(other.storage_) {}
214 template <
typename U> ObjectStorage(
const ObjectStorage<U, Cascade>& other): Cascade(other), storage_(other.storage()) {}
215 ObjectStorage(TSelf&& other)
noexcept:
216 Cascade(std::forward<Cascade>(other)),
217 storage_(other.storage_)
219 other.storage_ =
nullptr;
222 TPointer pointer()
const {
return storage_; }
230 bool isNull()
const {
return !storage_; }
231 void swap(TSelf& other) { Cascade::swap(other); std::swap(storage_, other.storage_); }
233 template <
typename U>
const ObjectStorage<U, Cascade> staticCast()
const
235 return ObjectStorage<U, Cascade>(
static_cast<U*
>(storage_), *
this);
238 template <
typename U>
const ObjectStorage<U, Cascade> dynamicCast()
const
240 if (U* p =
dynamic_cast<U*
>(storage_))
242 return ObjectStorage<U, Cascade>(p, *
this);
244 return ObjectStorage<U, Cascade>();
247 template <
typename U>
const ObjectStorage<U, Cascade> constCast()
const
249 return ObjectStorage<U, Cascade>(
const_cast<U*
>(storage_), *
this);
252 static TStorage defaultStorage() {
return 0; }
256 template <
typename U,
typename C>
friend class ObjectStorage;
257 template <
typename U,
template <
typename,
typename>
class S,
typename C>
friend class SharedPtr;
259 ObjectStorage(T* pointee,
const Cascade& cascade): Cascade(cascade), storage_(pointee) {}
278 typename Cascade = meta::EmptyType
280class ArrayStorage:
public Cascade
284 typedef ArrayStorage<T, Cascade> TSelf;
287 typedef T& TReference;
289 TStorage& storage() {
return storage_; }
290 const TStorage& storage()
const {
return storage_; }
294 ArrayStorage(): Cascade(), storage_(defaultStorage()) { }
295 explicit ArrayStorage(T* pointee): Cascade(), storage_(pointee) { }
296 ArrayStorage(
const TSelf& other): Cascade(other), storage_(other.storage_) {}
297 template <
typename U> ArrayStorage(
const ArrayStorage<U, Cascade>& other): Cascade(other), storage_(other.storage()) {}
298 ArrayStorage(TSelf&& other)
noexcept:
299 Cascade(std::forward<Cascade>(other)),
300 storage_(other.storage_)
302 other.storage_ =
nullptr;
305 TPointer pointer()
const {
return storage_; }
306 TReference at(
size_t index)
const {
return storage_[index]; }
314 bool isNull()
const {
return !storage_; }
315 void swap(TSelf& other) { Cascade::swap(other); std::swap(storage_, other.storage_); }
317 static TStorage defaultStorage() {
return 0; }
344 typedef size_t TCount;
348 DefaultCounter(): count_(
nullptr) {}
349 DefaultCounter(
const DefaultCounter& other): count_(other.count_) {}
350 DefaultCounter(DefaultCounter&& other)
noexcept:
353 other.count_ =
nullptr;
356 template <
typename TStorage>
void init(TStorage& )
358 count_ = initHeapCounter(1);
359 LASS_ASSERT(count_ && count_->load(std::memory_order_relaxed) == 1);
362 template <
typename TStorage>
void dispose(TStorage& )
364 LASS_ASSERT(count_ && count_->load(std::memory_order_relaxed) == 0);
365 disposeHeapCounter(count_);
369 template <
typename TStorage>
void increment(TStorage& )
372 [[maybe_unused]]
const TCount oldCount = count_->fetch_add(1, std::memory_order_relaxed);
373 LASS_ASSERT(oldCount >= 1);
376 template <
typename TStorage>
bool decrement(TStorage& )
379 const TCount oldCount = count_->fetch_sub(1, std::memory_order_release);
380 LASS_ASSERT(oldCount > 0);
384 std::atomic_thread_fence(std::memory_order_acquire);
390 template <
typename TStorage> TCount count(TStorage& )
const
393 const TCount count = count_->load(std::memory_order_relaxed);
394 LASS_ASSERT(count > 0);
398 void swap(DefaultCounter& other) { std::swap(count_, other.count_); }
402 typedef std::atomic<TCount> TAtomicCount;
404 LASS_DLL TAtomicCount* initHeapCounter(TCount initialValue);
405 LASS_DLL void disposeHeapCounter(TAtomicCount* counter);
407 TAtomicCount* count_;
453 typename CounterType,
454 CounterType T::* referenceCounter
462 typename CounterType,
463 volatile CounterType T::* referenceCounter
466[[deprecated(
"IntrusiveCounter with volatile count is deprecated, use it with std::atomic instead")]]
472 typedef CounterType TCount;
476 template <
typename TStorage>
void init(TStorage& pointee)
478 LASS_ASSERT(pointee);
479 (pointee->*referenceCounter) = 1;
482 template <
typename TStorage>
void dispose(TStorage& LASS_UNUSED(pointee))
484 LASS_ASSERT(pointee && (pointee->*referenceCounter) == 0);
487 template <
typename TStorage>
void increment(TStorage& pointee)
489 LASS_ASSERT(pointee);
490 TCount oldCount = 0, newCount = 0;
493 oldCount = pointee->*referenceCounter;
494 LASS_ASSERT(oldCount > 0);
495 newCount = oldCount + 1;
497 while (!atomicCompareAndSwap(pointee->*referenceCounter, oldCount, newCount));
500 template <
typename TStorage>
bool decrement(TStorage& pointee)
502 LASS_ASSERT(pointee);
503 TCount oldCount = 0, newCount = 0;
506 oldCount = pointee->*referenceCounter;
507 LASS_ASSERT(oldCount > 0);
508 newCount = oldCount - 1;
511 return newCount == 0;
514 template <
typename TStorage> TCount count(TStorage& pointee)
const
516 LASS_ASSERT(pointee && (pointee->*referenceCounter) > 0);
517 return pointee->*referenceCounter;
529 typename CounterType,
530 std::atomic<CounterType> T::* referenceCounter
536 typedef IntrusiveCounter<T, std::atomic<CounterType>, referenceCounter> TSelf;
537 typedef CounterType TCount;
541 template <
typename TStorage>
void init(TStorage& pointee)
543 LASS_ASSERT(pointee);
544 (pointee->*referenceCounter).store(1, std::memory_order_relaxed);
547 template <
typename TStorage>
void dispose([[maybe_unused]] TStorage& pointee)
549 LASS_ASSERT(pointee && (pointee->*referenceCounter).load(std::memory_order_relaxed) == 0);
552 template <
typename TStorage>
void increment(TStorage& pointee)
554 LASS_ASSERT(pointee);
555 [[maybe_unused]]
const TCount oldCount = (pointee->*referenceCounter).fetch_add(1, std::memory_order_relaxed);
556 LASS_ASSERT(oldCount >= 1);
559 template <
typename TStorage>
bool decrement(TStorage& pointee)
561 LASS_ASSERT(pointee);
562 const TCount oldCount = (pointee->*referenceCounter).fetch_sub(1, std::memory_order_release);
563 LASS_ASSERT(oldCount > 0);
567 std::atomic_thread_fence(std::memory_order_acquire);
573 template <
typename TStorage> TCount count(TStorage& pointee)
const
575 LASS_ASSERT(pointee );
576 const TCount count = (pointee->*referenceCounter).load(std::memory_order_relaxed);
577 LASS_ASSERT(count > 0);
implementation of CounterPolicy concept, using a counter in the managed object itself.
bool atomicCompareAndSwap(volatile T &dest, T expectedValue, T newValue)
Performs the following pseudocode in an atomic way (no other threads can intervene):
#define LASS_DLL
DLL interface: import or export symbols?
general utility, debug facilities, ...
Library for Assembled Shared Sources.