12#ifndef _INTERLOCKED_DECLARED_
13#define _INTERLOCKED_DECLARED_
16#pragma intrinsic(_InterlockedIncrement)
17#pragma intrinsic(_InterlockedDecrement)
28 return __sync_add_and_fetch(pLocation, 1);
36 return __sync_sub_and_fetch(pLocation, 1);
42 template <
typename T,
typename =
void>
46 struct IsComplete<T, std::void_t<decltype(sizeof(T))>> : std::true_type {};
60 class EnableSharedFromThis;
87 if constexpr (!std::is_abstract_v<T> && std::is_default_constructible_v<T>) {
89 m_pnRefCount =
nullptr;
92 m_pnRefCount =
nullptr;
96 m_pnRefCount =
nullptr;
107 if constexpr (!std::is_abstract_v<T> && std::is_default_constructible_v<T>) {
109 m_pnRefCount = bIsShared ?
new long(1) :
nullptr;
110 SetupEnableSharedFromThis(m_pObject);
113 m_pnRefCount =
nullptr;
117 m_pnRefCount =
nullptr;
127 explicit SmartPointer(T* pPtr) : m_pObject(pPtr), m_pnRefCount(nullptr) {}
136 m_pnRefCount((bIsShared && pPtr != nullptr) ? new long(1) : nullptr) {
137 SetupEnableSharedFromThis(m_pObject);
143 SmartPointer(std::nullptr_t) : m_pObject(nullptr), m_pnRefCount(nullptr) {}
159 if (objOther.m_pnRefCount ==
nullptr && objOther.m_pObject !=
nullptr) {
160 throw SystemException(
"Cannot copy a Unique SmartPointer. Use Move semantics or initialize as Shared.");
162 m_pObject = objOther.m_pObject;
163 m_pnRefCount = objOther.m_pnRefCount;
164 if (m_pnRefCount !=
nullptr) {
169 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
171 if (objOther.m_pnRefCount ==
nullptr && objOther.m_pObject !=
nullptr) {
172 throw SystemException(
"Cannot copy a Unique SmartPointer. Use Move semantics or initialize as Shared.");
174 m_pObject = objOther.m_pObject;
175 m_pnRefCount = objOther.m_pnRefCount;
176 if (m_pnRefCount !=
nullptr) {
185 if (
this != &objOther) {
186 if (objOther.m_pnRefCount ==
nullptr && objOther.m_pObject !=
nullptr) {
190 m_pObject = objOther.m_pObject;
191 m_pnRefCount = objOther.m_pnRefCount;
192 if (m_pnRefCount !=
nullptr) {
199 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
201 if (objOther.m_pnRefCount ==
nullptr && objOther.m_pObject !=
nullptr) {
205 m_pObject = objOther.m_pObject;
206 m_pnRefCount = objOther.m_pnRefCount;
207 if (m_pnRefCount !=
nullptr) {
219 : m_pObject(objOther.m_pObject), m_pnRefCount(objOther.m_pnRefCount) {
220 objOther.m_pObject =
nullptr;
221 objOther.m_pnRefCount =
nullptr;
224 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
226 : m_pObject(objOther.m_pObject), m_pnRefCount(objOther.m_pnRefCount) {
227 objOther.m_pObject =
nullptr;
228 objOther.m_pnRefCount =
nullptr;
235 if (
this != &objOther) {
237 m_pObject = objOther.m_pObject;
238 m_pnRefCount = objOther.m_pnRefCount;
239 objOther.m_pObject =
nullptr;
240 objOther.m_pnRefCount =
nullptr;
245 template <
typename U,
typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
247 if (
static_cast<const void*
>(
this) !=
static_cast<const void*
>(&objOther)) {
249 m_pObject = objOther.m_pObject;
250 m_pnRefCount = objOther.m_pnRefCount;
251 objOther.m_pObject =
nullptr;
252 objOther.m_pnRefCount =
nullptr;
269 template <
typename Arg1,
typename... Args>
271 return SmartPointer<T>(
new T(std::forward<Arg1>(arg1), std::forward<Args>(args)...),
false);
284 template <
typename Arg1,
typename... Args>
286 return SmartPointer<T>(
new T(std::forward<Arg1>(arg1), std::forward<Args>(args)...),
true);
301 template <
typename Arg1,
typename... Args>
303 return NewUnique(std::forward<Arg1>(arg1), std::forward<Args>(args)...);
318 template <
typename Arg1,
typename... Args>
320 return NewUnique(std::forward<Arg1>(arg1), std::forward<Args>(args)...);
333 template <
typename Arg1,
typename... Args>
335 return NewShared(std::forward<Arg1>(arg1), std::forward<Args>(args)...);
345 void Attach(T* pPtr,
bool bIsShared =
false) {
346 Reset(pPtr, bIsShared);
358 m_pnRefCount =
nullptr;
366 void Reset(T* pPtr,
bool bIsShared) {
369 m_pnRefCount = (bIsShared && pPtr !=
nullptr) ?
new long(1) :
nullptr;
370 SetupEnableSharedFromThis(m_pObject);
379 T* pTemp = m_pObject;
380 m_pnRefCount =
nullptr;
388 T*
Get() const noexcept {
return m_pObject; }
393 bool IsNull() const noexcept {
return m_pObject ==
nullptr; }
398 template <
typename U>
400 U* pCast =
dynamic_cast<U*
>(m_pObject);
408 template <
typename U>
410 U* pCast =
static_cast<U*
>(m_pObject);
418 template <
typename U>
420 U* pCast =
const_cast<U*
>(m_pObject);
425 template <
typename From>
430 template <
typename From>
435 template <
typename From>
444 return (m_pnRefCount !=
nullptr) ?
static_cast<int>(*m_pnRefCount) : 0;
451 explicit operator bool() const noexcept {
return m_pObject !=
nullptr; }
454 return m_pObject == other.m_pObject;
458 return m_pObject != other.m_pObject;
461 template <
typename U>
463 return m_pObject == other.Get();
466 template <
typename U>
468 return m_pObject != other.Get();
472 return m_pObject ==
nullptr;
476 return m_pObject !=
nullptr;
480 return sp.m_pObject ==
nullptr;
484 return sp.m_pObject !=
nullptr;
487 template <
typename U>
489 return m_pObject == pOther;
492 template <
typename U>
494 return m_pObject != pOther;
497 template <
typename U>
499 return pOther == sp.m_pObject;
502 template <
typename U>
504 return pOther != sp.m_pObject;
509 : m_pObject(pPtr), m_pnRefCount(pnRefCount) {
510 if (m_pnRefCount !=
nullptr) {
513 SetupEnableSharedFromThis(m_pObject);
516 template <
typename U>
517 void SetupEnableSharedFromThis(U* pPtr) {
518 if constexpr (IsComplete<U>::value) {
519 if (pPtr !=
nullptr && m_pnRefCount !=
nullptr) {
520 if constexpr (std::is_base_of_v<EnableSharedFromThisBase, U>) {
521 static_cast<EnableSharedFromThisBase*
>(pPtr)->m_pnRefCount = m_pnRefCount;
522 }
else if constexpr (std::is_polymorphic_v<U>) {
523 if (
auto* pBase =
dynamic_cast<EnableSharedFromThisBase*
>(pPtr)) {
524 pBase->m_pnRefCount = m_pnRefCount;
531 void InternalCleanup() {
533 if (m_pnRefCount !=
nullptr) {
535 if (m_pObject !=
nullptr)
delete m_pObject;
536 delete const_cast<long*
>(m_pnRefCount);
538 }
else if (m_pObject !=
nullptr) {
543 m_pnRefCount =
nullptr;
547 volatile long* m_pnRefCount;
550 template <
typename T>
555 throw SystemException(
"SharedFromThis called on an object that is not managed by a shared SmartPointer.");
562 throw SystemException(
"SharedFromThis called on an object that is not managed by a shared SmartPointer.");
574 template <
typename To,
typename From>
579 template <
typename To,
typename From>
584 template <
typename To,
typename From>
586 return sp.template ConstCast<To>();
589 template <
typename To,
typename From>
594 template <
typename To,
typename From>
Defines common cross-platform macros, export decorators, and fundamental types.
long __cdecl _InterlockedIncrement(long volatile *Addend)
long __cdecl _InterlockedDecrement(long volatile *Addend)
Serves as the base class for system exceptions across the library.
volatile long * m_pnRefCount
constexpr EnableSharedFromThisBase() noexcept
EnableSharedFromThisBase & operator=(const EnableSharedFromThisBase &) noexcept
virtual ~EnableSharedFromThisBase()=default
EnableSharedFromThisBase(const EnableSharedFromThisBase &) noexcept
EnableSharedFromThis & operator=(const EnableSharedFromThis &) noexcept
SmartPointer< T > SharedFromThis()
constexpr EnableSharedFromThis() noexcept=default
SmartPointer< const T > SharedFromThis() const
virtual ~EnableSharedFromThis()=default
A unified smart pointer that supports both unique and shared ownership semantics.
static SmartPointer< T > NewShared()
Creates a Shared SmartPointer, default constructing T.
bool operator==(const U *pOther) const noexcept
bool operator==(const SmartPointer< U > &other) const noexcept
SmartPointer(SmartPointer &&objOther) noexcept
Move constructor. Transfers ownership from the source.
SmartPointer(std::nullptr_t)
Explicit null constructor.
T * Detach()
Detaches the managed object and returns it. The SmartPointer will no longer own the object.
static SmartPointer< T > NewUnique()
Creates a Unique SmartPointer, default constructing T.
T * operator->() const noexcept
SmartPointer(const SmartPointer &objOther)
Copy constructor. Only permitted if the source is in Shared mode.
static SmartPointer< T > MakeUnique(Arg1 &&arg1, Args &&... args)
Alias for NewUnique. Provided for compatibility.
bool operator!=(std::nullptr_t) const noexcept
void Reset(TimeProvider *pPtr=nullptr)
static SmartPointer< T > StaticCast(const SmartPointer< From > &sp)
void Reset(T *pPtr, bool bIsShared)
Resets the SmartPointer with a specific ownership mode.
~SmartPointer()
Destructor. Cleans up the managed object based on ownership mode.
friend bool operator!=(const U *pOther, const SmartPointer &sp) noexcept
SmartPointer(bool bIsShared)
Constructor with ownership mode flag. Automatically allocates a new instance of T.
static SmartPointer< T > MakeUnique()
Alias for NewUnique (default construction).
SmartPointer & operator=(SmartPointer< U > &&objOther) noexcept
bool IsNull() const noexcept
Checks if the SmartPointer is null.
T * Get() const noexcept
Gets the raw pointer.
static SmartPointer< T > NewShared(Arg1 &&arg1, Args &&... args)
Creates a Shared SmartPointer, forwarding arguments to T's constructor.
static SmartPointer< T > ConstCast(const SmartPointer< From > &sp)
friend bool operator!=(std::nullptr_t, const SmartPointer &sp) noexcept
friend class SmartPointer
SmartPointer< U > ConstCast() const
Const casts the managed pointer to another type U and returns a new SmartPointer sharing ownership.
bool operator==(const SmartPointer &other) const noexcept
int GetRefCount() const noexcept
Gets the current reference count. Returns 0 for Unique or Null pointers.
SmartPointer(SmartPointer< U > &&objOther) noexcept
SmartPointer & operator=(SmartPointer &&objOther) noexcept
Move assignment operator. Transfers ownership from the source.
friend class EnableSharedFromThis
bool operator!=(const SmartPointer &other) const noexcept
bool operator!=(const U *pOther) const noexcept
friend bool operator==(std::nullptr_t, const SmartPointer &sp) noexcept
static SmartPointer< T > New(Arg1 &&arg1, Args &&... args)
Creates a new SmartPointer with variadic arguments for T's constructor.
SmartPointer(T *pPtr, bool bIsShared)
Constructor that specifies ownership mode for a raw pointer.
void Attach(T *pPtr, bool bIsShared=false)
Attaches a new raw pointer to the SmartPointer.
static SmartPointer< T > New()
Creates a new SmartPointer (default construction).
SmartPointer & operator=(const SmartPointer< U > &objOther)
SmartPointer()
Default constructor. For concrete types: Automatically allocates a new instance of T....
SmartPointer & operator=(const SmartPointer &objOther)
Copy assignment operator. Only permitted if the source is in Shared mode.
SmartPointer< U > DynamicCast() const
Dynamically casts the managed pointer to another type U and returns a new SmartPointer sharing owners...
bool operator==(std::nullptr_t) const noexcept
static SmartPointer< T > MakeShared()
Alias for NewShared (default construction).
static SmartPointer< T > NewUnique(Arg1 &&arg1, Args &&... args)
Creates a Unique SmartPointer, forwarding arguments to T's constructor.
SmartPointer(const SmartPointer< U > &objOther)
bool operator!=(const SmartPointer< U > &other) const noexcept
static SmartPointer< T > MakeShared(Arg1 &&arg1, Args &&... args)
Alias for NewShared. Provided for compatibility.
static SmartPointer< T > DynamicCast(const SmartPointer< From > &sp)
SmartPointer(T *pPtr)
Constructor for explicit raw pointer attachment.
SmartPointer< U > StaticCast() const
Statically casts the managed pointer to another type U and returns a new SmartPointer sharing ownersh...
friend bool operator==(const U *pOther, const SmartPointer &sp) noexcept
SystemException()
Initializes a new instance of the SystemException class with a default message.
long AtomicIncrement(volatile long *pLocation)
long AtomicDecrement(volatile long *pLocation)
SmartPointer< To > ConstPointerCast(const SmartPointer< From > &sp)
SmartPointer< To > DynamicPointerCast(const SmartPointer< From > &sp)
SmartPointer< To > StaticCast(const SmartPointer< From > &sp)
SmartPointer< To > DynamicCast(const SmartPointer< From > &sp)
SmartPointer< To > StaticPointerCast(const SmartPointer< From > &sp)