diff --git a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp index cc7aea0..17d48d4 100644 --- a/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp +++ b/Redcraft.Utility/Source/Private/Testing/TemplatesTesting.cpp @@ -574,6 +574,7 @@ void TestAny() FAny TempC = static_cast(16); FAny TempD = static_cast(32); + always_check(TempA == TempA); always_check(TempA != TempB); always_check(TempB != TempC); always_check(TempB != TempC); diff --git a/Redcraft.Utility/Source/Public/Memory/Memory.h b/Redcraft.Utility/Source/Public/Memory/Memory.h index 1ee8d15..471269f 100644 --- a/Redcraft.Utility/Source/Public/Memory/Memory.h +++ b/Redcraft.Utility/Source/Public/Memory/Memory.h @@ -18,12 +18,12 @@ inline constexpr size_t MinimumAlignment = 8; #ifdef __cpp_lib_hardware_interference_size -inline constexpr size_t DestructiveInterference = std::hardware_destructive_interference_size; +inline constexpr size_t DestructiveInterference = std::hardware_destructive_interference_size; inline constexpr size_t ConstructiveInterference = std::hardware_constructive_interference_size; #else -inline constexpr size_t DestructiveInterference = 64; +inline constexpr size_t DestructiveInterference = 64; inline constexpr size_t ConstructiveInterference = 64; #endif diff --git a/Redcraft.Utility/Source/Public/Templates/Any.h b/Redcraft.Utility/Source/Public/Templates/Any.h index 6c83f32..8cb6bd9 100644 --- a/Redcraft.Utility/Source/Public/Templates/Any.h +++ b/Redcraft.Utility/Source/Public/Templates/Any.h @@ -74,7 +74,7 @@ static_assert(CAnyCustomStorage); // You can add custom storage area through CustomStorage, such as TFunction // It is not recommended to use this, FAny is recommended -template +template class TAny { public: @@ -142,8 +142,8 @@ public: EmplaceImpl(Forward(Args)...); } - template requires (!CSameAs, TAny> && !CTInPlaceType>) - && CDestructible> && CConstructibleFrom, T&&> + template requires (!CBaseOf> && !CTInPlaceType> + && CDestructible> && CConstructibleFrom, T&&>) FORCEINLINE TAny(T&& InValue) : TAny(InPlaceType>, Forward(InValue)) { } @@ -254,8 +254,8 @@ public: return *this; } - template requires (!CSameAs, TAny> && !CTInPlaceType>) - && CDestructible> && CConstructibleFrom, T&&> + template requires (!CBaseOf> && !CTInPlaceType> + && CDestructible> && CConstructibleFrom, T&&>) FORCEINLINE TAny& operator=(T&& InValue) { using SelectedType = TDecay; @@ -481,10 +481,14 @@ private: if (LHS.IsValid() == false) return partial_ordering::equivalent; return LHS.GetTypeInfoImpl().SynthThreeWayCompareImpl(LHS.GetAllocation(), RHS.GetAllocation());; } - + }; -template +class FAny : STRONG_INHERIT(TAny); + +static_assert(sizeof(FAny) == 64, "The byte size of FAny is unexpected"); + +template requires (!CBaseOf>) constexpr bool operator==(const TAny& LHS, const T& RHS) { return LHS.template HoldsAlternative() ? LHS.template GetValue() == RHS : false; @@ -506,10 +510,6 @@ NAMESPACE_PRIVATE_END template concept CTAny = NAMESPACE_PRIVATE::TIsTAny>::Value; -using FAny = TAny<>; - -static_assert(sizeof(FAny) == 64, "The byte size of FAny is unexpected"); - NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Atomic.h b/Redcraft.Utility/Source/Public/Templates/Atomic.h index a1390be..6ad66f5 100644 --- a/Redcraft.Utility/Source/Public/Templates/Atomic.h +++ b/Redcraft.Utility/Source/Public/Templates/Atomic.h @@ -51,75 +51,75 @@ NAMESPACE_PRIVATE_END #endif -template requires (CTriviallyCopyable - && CCopyConstructible && CMoveConstructible - && CCopyAssignable && CMoveAssignable) -struct TAtomic : FSingleton +NAMESPACE_PRIVATE_BEGIN + +template +struct TAtomicImpl : FSingleton { protected: - using ElementType = TConditional, NAMESPACE_STD::atomic>; + using NativeAtomicType = TConditional, NAMESPACE_STD::atomic>; public: using ValueType = T; - static constexpr bool bIsAlwaysLockFree = ElementType::is_always_lock_free; + static constexpr bool bIsAlwaysLockFree = NativeAtomicType::is_always_lock_free; static constexpr size_t RequiredAlignment = NAMESPACE_STD::atomic_ref::required_alignment; - constexpr TAtomic() requires (!bIsRef) : Element() { }; - constexpr TAtomic(ValueType Desired) requires (!bIsRef) : Element(Desired) { }; + constexpr TAtomicImpl() requires (!bIsRef) : NativeAtomic() { }; + constexpr TAtomicImpl(ValueType Desired) requires (!bIsRef) : NativeAtomic(Desired) { }; - FORCEINLINE explicit TAtomic(ValueType& Desired) requires (bIsRef) : Element(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); }; - FORCEINLINE TAtomic(TAtomic& InValue) requires (bIsRef) : Element(InValue) { }; + FORCEINLINE explicit TAtomicImpl(ValueType& Desired) requires (bIsRef) : NativeAtomic(Desired) { check(Memory::IsAligned(&Desired, RequiredAlignment)); }; + FORCEINLINE TAtomicImpl(TAtomicImpl& InValue) requires (bIsRef) : NativeAtomic(InValue) { }; - FORCEINLINE ValueType operator=(ValueType Desired) { return Element = Desired; } - FORCEINLINE ValueType operator=(ValueType Desired) volatile requires (bIsAlwaysLockFree) { return Element = Desired; } + FORCEINLINE ValueType operator=(ValueType Desired) { return NativeAtomic = Desired; } + FORCEINLINE ValueType operator=(ValueType Desired) volatile requires (bIsAlwaysLockFree) { return NativeAtomic = Desired; } - FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); Element.store(Desired, static_cast(Order)); } - FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); Element.store(Desired, static_cast(Order)); } + FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast(Order)); } + FORCEINLINE void Store(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.store(Desired, static_cast(Order)); } - FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return Element.load(static_cast(Order)); } - FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return Element.load(static_cast(Order)); } + FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast(Order)); } + FORCEINLINE ValueType Load(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.load(static_cast(Order)); } - FORCEINLINE operator ValueType() const { return static_cast(Element); } - FORCEINLINE operator ValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast(Element); } + FORCEINLINE operator ValueType() const { return static_cast(NativeAtomic); } + FORCEINLINE operator ValueType() const volatile requires (bIsAlwaysLockFree) { return static_cast(NativeAtomic); } - FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return Element.exchange(Desired, static_cast(Order)); } - FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { return Element.exchange(Desired, static_cast(Order)); } + FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return NativeAtomic.exchange(Desired, static_cast(Order)); } + FORCEINLINE ValueType Exchange(ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (bIsAlwaysLockFree) { return NativeAtomic.exchange(Desired, static_cast(Order)); } FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) { MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20); - if (bIsWeak) return Element.compare_exchange_weak(Expected, Desired, static_cast(Success), static_cast(Failure)); - else return Element.compare_exchange_strong(Expected, Desired, static_cast(Success), static_cast(Failure)); + if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast(Success), static_cast(Failure)); + else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast(Success), static_cast(Failure)); } FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Success, EMemoryOrder Failure, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree) { MEMORY_ORDER_CHECK(Failure, 0x01 | 0x02 | 0x04 | 0x20); - if (bIsWeak) return Element.compare_exchange_weak(Expected, Desired, static_cast(Success), static_cast(Failure)); - else return Element.compare_exchange_strong(Expected, Desired, static_cast(Success), static_cast(Failure)); + if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast(Success), static_cast(Failure)); + else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast(Success), static_cast(Failure)); } FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) { - if (bIsWeak) return Element.compare_exchange_weak(Expected, Desired, static_cast(Order)); - else return Element.compare_exchange_strong(Expected, Desired, static_cast(Order)); + if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast(Order)); + else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast(Order)); } FORCEINLINE bool CompareExchange(ValueType& Expected, ValueType Desired, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent, bool bIsWeak = false) volatile requires (bIsAlwaysLockFree) { - if (bIsWeak) return Element.compare_exchange_weak(Expected, Desired, static_cast(Order)); - else return Element.compare_exchange_strong(Expected, Desired, static_cast(Order)); + if (bIsWeak) return NativeAtomic.compare_exchange_weak(Expected, Desired, static_cast(Order)); + else return NativeAtomic.compare_exchange_strong(Expected, Desired, static_cast(Order)); } - FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); Element.wait(Old, static_cast(Order)); } - FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); Element.wait(Old, static_cast(Order)); } + FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast(Order)); } + FORCEINLINE void Wait(ValueType Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); NativeAtomic.wait(Old, static_cast(Order)); } - FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) Element.notify_all(); else Element.notify_one(); } - FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) Element.notify_all(); else Element.notify_one(); } + FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); } + FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) NativeAtomic.notify_all(); else NativeAtomic.notify_one(); } template requires (CInvocableResult) FORCEINLINE ValueType FetchFn(F&& Func, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) @@ -137,17 +137,17 @@ public: return Temp; } - FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral || CFloatingPoint) { return Element.fetch_add(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral || CFloatingPoint) && bIsAlwaysLockFree { return Element.fetch_add(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral || CFloatingPoint) { return NativeAtomic.fetch_add(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchAdd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral || CFloatingPoint) && bIsAlwaysLockFree { return NativeAtomic.fetch_add(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer ) { return Element.fetch_add(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer && bIsAlwaysLockFree) { return Element.fetch_add(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer ) { return NativeAtomic.fetch_add(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchAdd(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer && bIsAlwaysLockFree) { return NativeAtomic.fetch_add(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral || CFloatingPoint) { return Element.fetch_sub(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral || CFloatingPoint) && bIsAlwaysLockFree { return Element.fetch_sub(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral || CFloatingPoint) { return NativeAtomic.fetch_sub(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchSub(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral || CFloatingPoint) && bIsAlwaysLockFree { return NativeAtomic.fetch_sub(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer ) { return Element.fetch_sub(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer && bIsAlwaysLockFree) { return Element.fetch_sub(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CPointer ) { return NativeAtomic.fetch_sub(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchSub(ptrdiff InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CPointer && bIsAlwaysLockFree) { return NativeAtomic.fetch_sub(InValue, static_cast(Order)); } FORCEINLINE ValueType FetchMul(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral || CFloatingPoint) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old * InValue; }); } FORCEINLINE ValueType FetchMul(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral || CFloatingPoint) && bIsAlwaysLockFree { return FetchFn([InValue](ValueType Old) -> ValueType { return Old * InValue; }); } @@ -158,14 +158,14 @@ public: FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old % InValue; }); } FORCEINLINE ValueType FetchMod(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old % InValue; }); } - FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return Element.fetch_and(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return Element.fetch_and(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return NativeAtomic.fetch_and(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchAnd(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return NativeAtomic.fetch_and(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return Element.fetch_or(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return Element.fetch_or(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return NativeAtomic.fetch_or(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchOr(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return NativeAtomic.fetch_or(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return Element.fetch_xor(InValue, static_cast(Order)); } - FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return Element.fetch_xor(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return NativeAtomic.fetch_xor(InValue, static_cast(Order)); } + FORCEINLINE ValueType FetchXor(ValueType InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return NativeAtomic.fetch_xor(InValue, static_cast(Order)); } FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old << InValue; }); } FORCEINLINE ValueType FetchLsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old << InValue; }); } @@ -173,29 +173,29 @@ public: FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) requires (CIntegral ) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); } FORCEINLINE ValueType FetchRsh(size_t InValue, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile requires (CIntegral && bIsAlwaysLockFree) { return FetchFn([InValue](ValueType Old) -> ValueType { return Old >> InValue; }); } - FORCEINLINE ValueType operator++() requires ((CIntegral || CPointer) ) { return ++Element; } - FORCEINLINE ValueType operator++() volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return ++Element; } + FORCEINLINE ValueType operator++() requires ((CIntegral || CPointer) ) { return ++NativeAtomic; } + FORCEINLINE ValueType operator++() volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return ++NativeAtomic; } - FORCEINLINE ValueType operator++(int) requires ((CIntegral || CPointer) ) { return Element++; } - FORCEINLINE ValueType operator++(int) volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return Element++; } + FORCEINLINE ValueType operator++(int) requires ((CIntegral || CPointer) ) { return NativeAtomic++; } + FORCEINLINE ValueType operator++(int) volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return NativeAtomic++; } - FORCEINLINE ValueType operator--() requires ((CIntegral || CPointer) ) { return --Element; } - FORCEINLINE ValueType operator--() volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return --Element; } + FORCEINLINE ValueType operator--() requires ((CIntegral || CPointer) ) { return --NativeAtomic; } + FORCEINLINE ValueType operator--() volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return --NativeAtomic; } - FORCEINLINE ValueType operator--(int) requires ((CIntegral || CPointer) ) { return Element--; } - FORCEINLINE ValueType operator--(int) volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return Element--; } + FORCEINLINE ValueType operator--(int) requires ((CIntegral || CPointer) ) { return NativeAtomic--; } + FORCEINLINE ValueType operator--(int) volatile requires ((CIntegral || CPointer) && bIsAlwaysLockFree) { return NativeAtomic--; } - FORCEINLINE ValueType operator+=(ValueType InValue) requires ((CIntegral || CFloatingPoint) ) { return Element += InValue; } - FORCEINLINE ValueType operator+=(ValueType InValue) volatile requires ((CIntegral || CFloatingPoint) && bIsAlwaysLockFree) { return Element += InValue; } + FORCEINLINE ValueType operator+=(ValueType InValue) requires ((CIntegral || CFloatingPoint) ) { return NativeAtomic += InValue; } + FORCEINLINE ValueType operator+=(ValueType InValue) volatile requires ((CIntegral || CFloatingPoint) && bIsAlwaysLockFree) { return NativeAtomic += InValue; } - FORCEINLINE ValueType operator+=(ptrdiff InValue) requires (CPointer ) { return Element += InValue; } - FORCEINLINE ValueType operator+=(ptrdiff InValue) volatile requires (CPointer && bIsAlwaysLockFree) { return Element += InValue; } + FORCEINLINE ValueType operator+=(ptrdiff InValue) requires (CPointer ) { return NativeAtomic += InValue; } + FORCEINLINE ValueType operator+=(ptrdiff InValue) volatile requires (CPointer && bIsAlwaysLockFree) { return NativeAtomic += InValue; } - FORCEINLINE ValueType operator-=(ValueType InValue) requires ((CIntegral || CFloatingPoint) ) { return Element -= InValue; } - FORCEINLINE ValueType operator-=(ValueType InValue) volatile requires ((CIntegral || CFloatingPoint) && bIsAlwaysLockFree) { return Element -= InValue; } + FORCEINLINE ValueType operator-=(ValueType InValue) requires ((CIntegral || CFloatingPoint) ) { return NativeAtomic -= InValue; } + FORCEINLINE ValueType operator-=(ValueType InValue) volatile requires ((CIntegral || CFloatingPoint) && bIsAlwaysLockFree) { return NativeAtomic -= InValue; } - FORCEINLINE ValueType operator-=(ptrdiff InValue) requires (CPointer ) { return Element -= InValue; } - FORCEINLINE ValueType operator-=(ptrdiff InValue) volatile requires (CPointer && bIsAlwaysLockFree) { return Element -= InValue; } + FORCEINLINE ValueType operator-=(ptrdiff InValue) requires (CPointer ) { return NativeAtomic -= InValue; } + FORCEINLINE ValueType operator-=(ptrdiff InValue) volatile requires (CPointer && bIsAlwaysLockFree) { return NativeAtomic -= InValue; } FORCEINLINE ValueType operator*=(ValueType InValue) requires ((CIntegral || CFloatingPoint) ) { return FetchMul(InValue) * InValue; } FORCEINLINE ValueType operator*=(ValueType InValue) volatile requires ((CIntegral || CFloatingPoint) && bIsAlwaysLockFree) { return FetchMul(InValue) * InValue; } @@ -206,14 +206,14 @@ public: FORCEINLINE ValueType operator%=(ValueType InValue) requires (CIntegral ) { return FetchMod(InValue) % InValue; } FORCEINLINE ValueType operator%=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return FetchMod(InValue) % InValue; } - FORCEINLINE ValueType operator&=(ValueType InValue) requires (CIntegral ) { return Element &= InValue; } - FORCEINLINE ValueType operator&=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return Element &= InValue; } + FORCEINLINE ValueType operator&=(ValueType InValue) requires (CIntegral ) { return NativeAtomic &= InValue; } + FORCEINLINE ValueType operator&=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return NativeAtomic &= InValue; } - FORCEINLINE ValueType operator|=(ValueType InValue) requires (CIntegral ) { return Element |= InValue; } - FORCEINLINE ValueType operator|=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return Element |= InValue; } + FORCEINLINE ValueType operator|=(ValueType InValue) requires (CIntegral ) { return NativeAtomic |= InValue; } + FORCEINLINE ValueType operator|=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return NativeAtomic |= InValue; } - FORCEINLINE ValueType operator^=(ValueType InValue) requires (CIntegral ) { return Element ^= InValue; } - FORCEINLINE ValueType operator^=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return Element ^= InValue; } + FORCEINLINE ValueType operator^=(ValueType InValue) requires (CIntegral ) { return NativeAtomic ^= InValue; } + FORCEINLINE ValueType operator^=(ValueType InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return NativeAtomic ^= InValue; } FORCEINLINE ValueType operator<<=(size_t InValue) requires (CIntegral ) { return FetchLsh(InValue) << InValue; } FORCEINLINE ValueType operator<<=(size_t InValue) volatile requires (CIntegral && bIsAlwaysLockFree) { return FetchLsh(InValue) << InValue; } @@ -223,40 +223,50 @@ public: protected: - ElementType Element; + NativeAtomicType NativeAtomic; }; +NAMESPACE_PRIVATE_END + template -using TAtomicRef = TAtomic; +struct TAtomic : STRONG_INHERIT(NAMESPACE_PRIVATE::TAtomicImpl); + +template +struct TAtomicRef : STRONG_INHERIT(NAMESPACE_PRIVATE::TAtomicImpl); template TAtomic(T) -> TAtomic; +template +TAtomicRef(T&) -> TAtomicRef; + +static_assert(sizeof(TAtomic) == sizeof(int32), "The byte size of TAtomic is unexpected"); + struct FAtomicFlag : FSingleton { public: - constexpr FAtomicFlag() : Element() { }; + constexpr FAtomicFlag() : NativeAtomic() { }; - FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); Element.clear(static_cast(Order)); } - FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); Element.clear(static_cast(Order)); } + FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.clear(static_cast(Order)); } + FORCEINLINE void Clear(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x08 | 0x20); NativeAtomic.clear(static_cast(Order)); } - FORCEINLINE bool TestAndSet(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return Element.test_and_set(static_cast(Order)); } - FORCEINLINE bool TestAndSet(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { return Element.test_and_set(static_cast(Order)); } + FORCEINLINE bool TestAndSet(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) { return NativeAtomic.test_and_set(static_cast(Order)); } + FORCEINLINE bool TestAndSet(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) volatile { return NativeAtomic.test_and_set(static_cast(Order)); } - FORCEINLINE bool Test(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return Element.test(static_cast(Order)); } - FORCEINLINE bool Test(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return Element.test(static_cast(Order)); } + FORCEINLINE bool Test(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.test(static_cast(Order)); } + FORCEINLINE bool Test(EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); return NativeAtomic.test(static_cast(Order)); } - FORCEINLINE void Wait(bool Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); const_cast(Element).wait(Old, static_cast(Order)); } - FORCEINLINE void Wait(bool Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); const_cast(Element).wait(Old, static_cast(Order)); } + FORCEINLINE void Wait(bool Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); const_cast(NativeAtomic).wait(Old, static_cast(Order)); } + FORCEINLINE void Wait(bool Old, EMemoryOrder Order = EMemoryOrder::SequentiallyConsistent) const volatile { MEMORY_ORDER_CHECK(Order, 0x01 | 0x02 | 0x04 | 0x20); const_cast(NativeAtomic).wait(Old, static_cast(Order)); } - FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) const_cast(Element).notify_all(); else const_cast(Element).notify_one(); } - FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) const_cast(Element).notify_all(); else const_cast(Element).notify_one(); } + FORCEINLINE void Notify(bool bIsAll = false) { if (bIsAll) const_cast(NativeAtomic).notify_all(); else const_cast(NativeAtomic).notify_one(); } + FORCEINLINE void Notify(bool bIsAll = false) volatile { if (bIsAll) const_cast(NativeAtomic).notify_all(); else const_cast(NativeAtomic).notify_one(); } -protected: +private: - NAMESPACE_STD::atomic_flag Element; + NAMESPACE_STD::atomic_flag NativeAtomic; }; diff --git a/Redcraft.Utility/Source/Public/Templates/Optional.h b/Redcraft.Utility/Source/Public/Templates/Optional.h index 35c64ea..0cc76bd 100644 --- a/Redcraft.Utility/Source/Public/Templates/Optional.h +++ b/Redcraft.Utility/Source/Public/Templates/Optional.h @@ -48,7 +48,7 @@ public: } template requires (CConstructibleFrom) - && (!CSameAs, FInPlace>) && (!CSameAs, TOptional>) + && (!CSameAs, FInPlace>) && (!CBaseOf>) constexpr explicit (!CConvertibleTo) TOptional(T&& InValue) : TOptional(InPlace, Forward(InValue)) { } diff --git a/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h b/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h index 3aa98d6..985531e 100644 --- a/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h +++ b/Redcraft.Utility/Source/Public/Templates/ReferenceWrapper.h @@ -161,7 +161,7 @@ public: { } template requires (CConstructibleFrom - && !CSameAs, FInPlace> && !CSameAs, TOptional>) + && !CSameAs, FInPlace> && !CBaseOf>) constexpr explicit (!CConvertibleTo) TOptional(T&& InValue) : TOptional(InPlace, Forward(InValue)) { } diff --git a/Redcraft.Utility/Source/Public/Templates/Tuple.h b/Redcraft.Utility/Source/Public/Templates/Tuple.h index 6ecacd1..8fe6117 100644 --- a/Redcraft.Utility/Source/Public/Templates/Tuple.h +++ b/Redcraft.Utility/Source/Public/Templates/Tuple.h @@ -597,7 +597,7 @@ template requires (sizeof...(LHSTyp constexpr bool operator==(const TTuple& LHS, const TTuple& RHS) { if constexpr (sizeof...(LHSTypes) != sizeof...(RHSTypes)) return false; - return[&LHS, &RHS](TIndexSequence) -> bool { return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); } (TMakeIndexSequence()); + return [&LHS, &RHS](TIndexSequence) -> bool { return (true && ... && (LHS.template GetValue() == RHS.template GetValue())); } (TMakeIndexSequence()); } template requires (sizeof...(LHSTypes) == sizeof...(RHSTypes) && (true && ... && (CSynthThreeWayComparable))) diff --git a/Redcraft.Utility/Source/Public/Templates/Utility.h b/Redcraft.Utility/Source/Public/Templates/Utility.h index 40968bc..4f9571a 100644 --- a/Redcraft.Utility/Source/Public/Templates/Utility.h +++ b/Redcraft.Utility/Source/Public/Templates/Utility.h @@ -102,6 +102,21 @@ struct FIgnore inline constexpr FIgnore Ignore; +// This macro is used in place of using type aliases, see Atomic.h, etc +#define STRONG_INHERIT(...) /* BaseClass */ \ + /* struct DerivedClass : */ public __VA_ARGS__ \ + { \ + private: \ + \ + using BaseClassTypedef = __VA_ARGS__; \ + \ + public: \ + \ + using BaseClassTypedef::BaseClassTypedef; \ + using BaseClassTypedef::operator=; \ + \ + } + NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Redcraft) NAMESPACE_REDCRAFT_END diff --git a/Redcraft.Utility/Source/Public/Templates/Variant.h b/Redcraft.Utility/Source/Public/Templates/Variant.h index 2ca362a..fcb9f83 100644 --- a/Redcraft.Utility/Source/Public/Templates/Variant.h +++ b/Redcraft.Utility/Source/Public/Templates/Variant.h @@ -189,7 +189,7 @@ public: template requires (NAMESPACE_PRIVATE::TVariantSelectedType, Ts...>::Value && !CTInPlaceType> && !CTInPlaceIndex> - && !CSameAs, TVariant>) + && !CBaseOf>) constexpr TVariant(T&& InValue) : TVariant(InPlaceType, Ts...>::Type>, Forward(InValue)) { } @@ -289,7 +289,7 @@ public: constexpr bool IsValid() const { return TypeIndex != 0xFF; } constexpr explicit operator bool() const { return TypeIndex != 0xFF; } - template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I : false; } + template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == I : false; } template constexpr bool HoldsAlternative() const { return IsValid() ? GetIndex() == TVariantIndex> : false; } template requires (I < sizeof...(Ts)) constexpr decltype(auto) GetValue() & { checkf(HoldsAlternative(), TEXT("It is an error to call GetValue() on an wrong TVariant. Please either check HoldsAlternative() or use Get(DefaultValue) instead.")); return *reinterpret_cast< TVariantAlternative>*>(&Value); } @@ -474,7 +474,7 @@ private: }; -template requires (!CSameAs> && CEqualityComparable) +template requires (!CBaseOf, T> && CEqualityComparable) constexpr bool operator==(const TVariant& LHS, const T& RHS) { return LHS.template HoldsAlternative() ? LHS.template GetValue() == RHS : false;