Compare commits

..

3 Commits

2 changed files with 52 additions and 52 deletions

View File

@ -151,7 +151,8 @@ public:
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent)
{ {
ValueType Temp(Load(EMemoryOrder::Relaxed)); ValueType Temp(Load(EMemoryOrder::Relaxed));
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order)); // We do a weak read here because we require a loop.
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order, true));
return Temp; return Temp;
} }
@ -160,7 +161,8 @@ public:
FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile
{ {
ValueType Temp(Load(EMemoryOrder::Relaxed)); ValueType Temp(Load(EMemoryOrder::Relaxed));
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order)); // We do a weak read here because we require a loop.
while (!CompareExchange(Temp, InvokeResult<ValueType>(Forward<F>(Func), Temp), Order, true));
return Temp; return Temp;
} }

View File

@ -1,7 +1,9 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Templates/Invoke.h"
#include "Templates/Utility.h" #include "Templates/Utility.h"
#include "Templates/Noncopyable.h"
#include "TypeTraits/PrimaryType.h" #include "TypeTraits/PrimaryType.h"
#include "TypeTraits/Miscellaneous.h" #include "TypeTraits/Miscellaneous.h"
#include "TypeTraits/TypeProperties.h" #include "TypeTraits/TypeProperties.h"
@ -14,24 +16,24 @@ NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_PRIVATE_BEGIN NAMESPACE_PRIVATE_BEGIN
template <typename T, typename E, bool = CEmpty<E> && !CFinal<E>> template <typename T, typename E, bool = CEmpty<E> && !CFinal<E>>
class TUniquePtrStorage; class TUniqueStorage;
template <typename T, typename E> template <typename T, typename E>
class TUniquePtrStorage<T, E, true> : private E class TUniqueStorage<T, E, true> : private E
{ {
public: public:
FORCEINLINE constexpr TUniquePtrStorage() = delete; FORCEINLINE constexpr TUniqueStorage() = delete;
FORCEINLINE constexpr TUniquePtrStorage(T* InPtr) : E(), Pointer(InPtr) { } FORCEINLINE constexpr TUniqueStorage(T* InPtr) : E(), Pointer(InPtr) { }
template<typename U> template<typename U>
FORCEINLINE constexpr TUniquePtrStorage(T* InPtr, U&& InDeleter) : E(Forward<U>(InDeleter)), Pointer(InPtr) { } FORCEINLINE constexpr TUniqueStorage(T* InPtr, U&& InDeleter) : E(Forward<U>(InDeleter)), Pointer(InPtr) { }
FORCEINLINE constexpr TUniquePtrStorage(const TUniquePtrStorage&) = delete; FORCEINLINE constexpr TUniqueStorage(const TUniqueStorage&) = delete;
FORCEINLINE constexpr TUniquePtrStorage(TUniquePtrStorage&& InValue) = default; FORCEINLINE constexpr TUniqueStorage(TUniqueStorage&& InValue) = default;
FORCEINLINE constexpr TUniquePtrStorage& operator=(const TUniquePtrStorage&) = delete; FORCEINLINE constexpr TUniqueStorage& operator=(const TUniqueStorage&) = delete;
FORCEINLINE constexpr TUniquePtrStorage& operator=(TUniquePtrStorage&&) = default; FORCEINLINE constexpr TUniqueStorage& operator=(TUniqueStorage&&) = default;
FORCEINLINE constexpr T*& GetPointer() { return Pointer; } FORCEINLINE constexpr T*& GetPointer() { return Pointer; }
FORCEINLINE constexpr T* GetPointer() const { return Pointer; } FORCEINLINE constexpr T* GetPointer() const { return Pointer; }
@ -48,21 +50,21 @@ private:
}; };
template <typename T, typename E> template <typename T, typename E>
class TUniquePtrStorage<T, E, false> class TUniqueStorage<T, E, false>
{ {
public: public:
FORCEINLINE constexpr TUniquePtrStorage() = delete; FORCEINLINE constexpr TUniqueStorage() = delete;
FORCEINLINE constexpr TUniquePtrStorage(T* InPtr) : E(), Pointer(InPtr) { } FORCEINLINE constexpr TUniqueStorage(T* InPtr) : E(), Pointer(InPtr) { }
template<typename U> template<typename U>
FORCEINLINE constexpr TUniquePtrStorage(T* InPtr, U&& InDeleter) : Pointer(InPtr), Deleter(Forward<U>(InDeleter)) { } FORCEINLINE constexpr TUniqueStorage(T* InPtr, U&& InDeleter) : Pointer(InPtr), Deleter(Forward<U>(InDeleter)) { }
FORCEINLINE constexpr TUniquePtrStorage(const TUniquePtrStorage&) = delete; FORCEINLINE constexpr TUniqueStorage(const TUniqueStorage&) = delete;
FORCEINLINE constexpr TUniquePtrStorage(TUniquePtrStorage&& InValue) = default; FORCEINLINE constexpr TUniqueStorage(TUniqueStorage&& InValue) = default;
FORCEINLINE constexpr TUniquePtrStorage& operator=(const TUniquePtrStorage&) = delete; FORCEINLINE constexpr TUniqueStorage& operator=(const TUniqueStorage&) = delete;
FORCEINLINE constexpr TUniquePtrStorage& operator=(TUniquePtrStorage&&) = default; FORCEINLINE constexpr TUniqueStorage& operator=(TUniqueStorage&&) = default;
FORCEINLINE constexpr T*& GetPointer() { return Pointer; } FORCEINLINE constexpr T*& GetPointer() { return Pointer; }
FORCEINLINE constexpr T* GetPointer() const { return Pointer; } FORCEINLINE constexpr T* GetPointer() const { return Pointer; }
@ -122,8 +124,7 @@ struct TDefaultDelete<T[]>
}; };
/** This is essentially a reference version of TUniquePtr. */ /** This is essentially a reference version of TUniquePtr. */
template <typename T, typename E = TDefaultDelete<T>> requires (CObject<T> && !CBoundedArray<T> && !CRValueReference<E> template <typename T, CInvocable<TRemoveExtent<T>*> E = TDefaultDelete<T>> requires (CObject<T> && !CBoundedArray<T> && (CDestructible<E> || CLValueReference<E>))
&& ((!CArray<T> && CInvocable<E, T*>) || (CArray<T> && CInvocable<E, TRemoveExtent<T>*>)))
class TUniqueRef final : private FSingleton class TUniqueRef final : private FSingleton
{ {
public: public:
@ -151,7 +152,7 @@ public:
} }
/** Destroy the owned object. */ /** Destroy the owned object. */
FORCEINLINE constexpr ~TUniqueRef() { GetDeleter()(Get()); } FORCEINLINE constexpr ~TUniqueRef() { Invoke(GetDeleter(), Get()); }
/** Compares the pointer values of two TUniqueRef. */ /** Compares the pointer values of two TUniqueRef. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() == RHS.Get(); } NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() == RHS.Get(); }
@ -172,7 +173,7 @@ public:
FORCEINLINE constexpr void Reset(T* InPtr) FORCEINLINE constexpr void Reset(T* InPtr)
{ {
checkf(InPtr != nullptr, TEXT("TUniqueRef cannot be initialized by nullptr. Please use TUniquePtr.")); checkf(InPtr != nullptr, TEXT("TUniqueRef cannot be initialized by nullptr. Please use TUniquePtr."));
GetDeleter()(Get()); Invoke(GetDeleter(), Get());
Storage.GetPointer() = InPtr; Storage.GetPointer() = InPtr;
} }
@ -214,8 +215,8 @@ public:
NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); } NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); }
/** @return The deleter that is used for destruction of the managed object. */ /** @return The deleter that is used for destruction of the managed object. */
NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); }
NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); }
/** @return The a reference or pointer to the object owned by *this, i.e. Get(). */ /** @return The a reference or pointer to the object owned by *this, i.e. Get(). */
NODISCARD FORCEINLINE constexpr T& operator*() const { return *Get(); } NODISCARD FORCEINLINE constexpr T& operator*() const { return *Get(); }
@ -233,7 +234,7 @@ public:
private: private:
NAMESPACE_PRIVATE::TUniquePtrStorage<T, E> Storage; NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
}; };
@ -271,7 +272,7 @@ public:
} }
/** Destroy the owned array. */ /** Destroy the owned array. */
FORCEINLINE constexpr ~TUniqueRef() { GetDeleter()(Get()); } FORCEINLINE constexpr ~TUniqueRef() { Invoke(GetDeleter(), Get()); }
/** Compares the pointer values of two TUniqueRef. */ /** Compares the pointer values of two TUniqueRef. */
NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() == RHS.Get(); } NODISCARD friend FORCEINLINE constexpr bool operator==(const TUniqueRef& LHS, const TUniqueRef& RHS) { return LHS.Get() == RHS.Get(); }
@ -295,7 +296,7 @@ public:
FORCEINLINE constexpr void Reset(U InPtr) FORCEINLINE constexpr void Reset(U InPtr)
{ {
checkf(InPtr != nullptr, TEXT("TUniqueRef cannot be initialized by nullptr. Please use TUniquePtr.")); checkf(InPtr != nullptr, TEXT("TUniqueRef cannot be initialized by nullptr. Please use TUniquePtr."));
GetDeleter()(Get()); Invoke(GetDeleter(), Get());
Storage.GetPointer() = InPtr; Storage.GetPointer() = InPtr;
} }
@ -340,8 +341,8 @@ public:
NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); } NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); }
/** @return The deleter that is used for destruction of the managed array. */ /** @return The deleter that is used for destruction of the managed array. */
NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); }
NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); }
/** @return The element at index, i.e. Get()[Index]. */ /** @return The element at index, i.e. Get()[Index]. */
NODISCARD FORCEINLINE constexpr T& operator[](size_t Index) const { return Get()[Index]; } NODISCARD FORCEINLINE constexpr T& operator[](size_t Index) const { return Get()[Index]; }
@ -358,13 +359,12 @@ public:
private: private:
NAMESPACE_PRIVATE::TUniquePtrStorage<T, E> Storage; NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
}; };
/** Single-ownership smart pointer. Use this when you need an object's lifetime to be strictly bound to the lifetime of a single smart pointer. */ /** Single-ownership smart pointer. Use this when you need an object's lifetime to be strictly bound to the lifetime of a single smart pointer. */
template <typename T, typename E = TDefaultDelete<T>> requires (CObject<T> && !CBoundedArray<T> && !CRValueReference<E> template <typename T, CInvocable<TRemoveExtent<T>*> E = TDefaultDelete<T>> requires (CObject<T> && !CBoundedArray<T> && (CDestructible<E> || CLValueReference<E>))
&& ((!CArray<T> && CInvocable<E, T*>) || (CArray<T> && CInvocable<E, TRemoveExtent<T>*>)))
class TUniquePtr final : private FNoncopyable class TUniquePtr final : private FNoncopyable
{ {
public: public:
@ -394,10 +394,10 @@ public:
FORCEINLINE constexpr TUniquePtr(TUniquePtr<U, InE>&& InValue) : Storage(InValue.Release(), Forward<InE>(InValue.GetDeleter())) { } FORCEINLINE constexpr TUniquePtr(TUniquePtr<U, InE>&& InValue) : Storage(InValue.Release(), Forward<InE>(InValue.GetDeleter())) { }
/** If !IsValid() there are no effects. Otherwise, the owned object is destroyed. */ /** If !IsValid() there are no effects. Otherwise, the owned object is destroyed. */
FORCEINLINE constexpr ~TUniquePtr() { if (IsValid()) GetDeleter()(Get()); } FORCEINLINE constexpr ~TUniquePtr() { if (IsValid()) Invoke(GetDeleter(), Get()); }
/** Move assignment operator. Transfers ownership from 'InValue' to *this. */ /** Move assignment operator. Transfers ownership from 'InValue' to *this. */
FORCEINLINE constexpr TUniquePtr& operator=(TUniquePtr&& InValue) FORCEINLINE constexpr TUniquePtr& operator=(TUniquePtr&& InValue) requires (!CReference<E> && CAssignableFrom<E&, E&&>)
{ {
Reset(InValue.Release()); Reset(InValue.Release());
GetDeleter() = Forward<E>(InValue.GetDeleter()); GetDeleter() = Forward<E>(InValue.GetDeleter());
@ -435,7 +435,7 @@ public:
/** Replaces the managed object. */ /** Replaces the managed object. */
FORCEINLINE constexpr void Reset(T* InPtr = nullptr) FORCEINLINE constexpr void Reset(T* InPtr = nullptr)
{ {
if (IsValid()) GetDeleter()(Get()); if (IsValid()) Invoke(GetDeleter(), Get());
Storage.GetPointer() = InPtr; Storage.GetPointer() = InPtr;
} }
@ -465,8 +465,8 @@ public:
NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); } NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); }
/** @return The deleter that is used for destruction of the managed object. */ /** @return The deleter that is used for destruction of the managed object. */
NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); }
NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); }
/** @return true if *this owns an object, false otherwise. */ /** @return true if *this owns an object, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; }
@ -488,10 +488,9 @@ public:
private: private:
NAMESPACE_PRIVATE::TUniquePtrStorage<T, E> Storage; NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
template <typename OtherT, typename OtherE> requires (CObject<OtherT> && !CBoundedArray<OtherT> && !CRValueReference<OtherE> template <typename OtherT, CInvocable<TRemoveExtent<OtherT>*> OtherE> requires (CObject<OtherT> && !CBoundedArray<OtherT> && (CDestructible<OtherE> || CLValueReference<OtherE>))
&& ((!CArray<OtherT> && CInvocable<OtherE, OtherT*>) || (CArray<OtherT> && CInvocable<OtherE, TRemoveExtent<OtherT>*>)))
friend class TUniquePtr; friend class TUniquePtr;
}; };
@ -527,15 +526,15 @@ public:
FORCEINLINE constexpr TUniquePtr(TUniquePtr&& InValue) : Storage(InValue.Release(), Forward<E>(InValue.GetDeleter())) { } FORCEINLINE constexpr TUniquePtr(TUniquePtr&& InValue) : Storage(InValue.Release(), Forward<E>(InValue.GetDeleter())) { }
/** Constructs a TUniquePtr by transferring ownership from 'InValue' to *this and stores the nullptr in 'InValue'. */ /** Constructs a TUniquePtr by transferring ownership from 'InValue' to *this and stores the nullptr in 'InValue'. */
template <typename U = T*, typename InE> requires (CConvertibleTo<U(*)[], T(*)[]> && CArray<U> template <typename U, typename InE> requires (CConvertibleTo<U(*)[], T(*)[]> && CArray<U>
&& ((CReference<E> && CSameAs<InE, E>) || (!CReference<E> && CConvertibleTo<InE, E>))) && ((CReference<E> && CSameAs<InE, E>) || (!CReference<E> && CConvertibleTo<InE, E>)))
FORCEINLINE constexpr TUniquePtr(TUniquePtr<U, InE>&& InValue) : Storage(InValue.Release(), Forward<InE>(InValue.GetDeleter())) { } FORCEINLINE constexpr TUniquePtr(TUniquePtr<U, InE>&& InValue) : Storage(InValue.Release(), Forward<InE>(InValue.GetDeleter())) { }
/** If !IsValid() there are no effects. Otherwise, the owned array is destroyed. */ /** If !IsValid() there are no effects. Otherwise, the owned array is destroyed. */
FORCEINLINE constexpr ~TUniquePtr() { if (IsValid()) GetDeleter()(Get()); } FORCEINLINE constexpr ~TUniquePtr() { if (IsValid()) Invoke(GetDeleter(), Get()); }
/** Move assignment operator. Transfers ownership from 'InValue' to *this. */ /** Move assignment operator. Transfers ownership from 'InValue' to *this. */
FORCEINLINE constexpr TUniquePtr& operator=(TUniquePtr&& InValue) FORCEINLINE constexpr TUniquePtr& operator=(TUniquePtr&& InValue) requires (!CReference<E> && CAssignableFrom<E&, E&&>)
{ {
Reset(InValue.Release()); Reset(InValue.Release());
GetDeleter() = Forward<E>(InValue.GetDeleter()); GetDeleter() = Forward<E>(InValue.GetDeleter());
@ -543,7 +542,7 @@ public:
} }
/** Move assignment operator. Transfers ownership from 'InValue' to *this. */ /** Move assignment operator. Transfers ownership from 'InValue' to *this. */
template <typename U = T*, typename InE> requires (CConvertibleTo<U(*)[], T(*)[]> template <typename U, typename InE> requires (CConvertibleTo<U(*)[], T(*)[]>
&& CArray<U> && !CReference<E> && CAssignableFrom<E&, InE&&>) && CArray<U> && !CReference<E> && CAssignableFrom<E&, InE&&>)
FORCEINLINE constexpr TUniquePtr& operator=(TUniquePtr<U, E>&& InValue) FORCEINLINE constexpr TUniquePtr& operator=(TUniquePtr<U, E>&& InValue)
{ {
@ -576,7 +575,7 @@ public:
template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>)) template <typename U = T*> requires (CNullPointer<U> || (CPointer<U> && CConvertibleTo<TRemovePointer<U>(*)[], T(*)[]>))
FORCEINLINE constexpr void Reset(U InPtr = nullptr) FORCEINLINE constexpr void Reset(U InPtr = nullptr)
{ {
if (IsValid()) GetDeleter()(Get()); if (IsValid()) Invoke(GetDeleter(), Get());
Storage.GetPointer() = InPtr; Storage.GetPointer() = InPtr;
} }
@ -609,8 +608,8 @@ public:
NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); } NODISCARD FORCEINLINE constexpr T* Get() const { return Storage.GetPointer(); }
/** @return The deleter that is used for destruction of the managed array. */ /** @return The deleter that is used for destruction of the managed array. */
NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr E& GetDeleter() { return Storage.GetDeleter(); }
NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); } NODISCARD FORCEINLINE constexpr const E& GetDeleter() const { return Storage.GetDeleter(); }
/** @return true if *this owns an array, false otherwise. */ /** @return true if *this owns an array, false otherwise. */
NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; } NODISCARD FORCEINLINE constexpr bool IsValid() const { return Get() != nullptr; }
@ -631,10 +630,9 @@ public:
private: private:
NAMESPACE_PRIVATE::TUniquePtrStorage<T, E> Storage; NAMESPACE_PRIVATE::TUniqueStorage<T, E> Storage;
template <typename OtherT, typename OtherE> requires (CObject<OtherT> && !CBoundedArray<OtherT> && !CRValueReference<OtherE> template <typename OtherT, CInvocable<TRemoveExtent<OtherT>*> OtherE> requires (CObject<OtherT> && !CBoundedArray<OtherT> && (CDestructible<OtherE> || CLValueReference<OtherE>))
&& ((!CArray<OtherT> && CInvocable<OtherE, OtherT*>) || (CArray<OtherT> && CInvocable<OtherE, TRemoveExtent<OtherT>*>)))
friend class TUniquePtr; friend class TUniquePtr;
}; };