From 83be3aa14291ad860562abaae641e9accc65edbf Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Wed, 6 Oct 2021 15:06:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=AF=B9=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E5=9F=BA=E7=A1=80=E5=86=85=E5=AD=98=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Redcraft.Core/Source/Public/CoreMinimal.h | 1 + Redcraft.Core/Source/Public/HAL/Memory.inl | 14 +- .../Source/Public/Templates/MemoryOps.h | 35 ++++ .../Source/Public/Templates/MemoryOps.inl | 186 ++++++++++++++++++ .../Source/Public/Templates/TypeTraits.h | 101 +++++++--- Redcraft.Debug/Source/Main.cpp | 45 ++++- 6 files changed, 350 insertions(+), 32 deletions(-) create mode 100644 Redcraft.Core/Source/Public/Templates/MemoryOps.h create mode 100644 Redcraft.Core/Source/Public/Templates/MemoryOps.inl diff --git a/Redcraft.Core/Source/Public/CoreMinimal.h b/Redcraft.Core/Source/Public/CoreMinimal.h index 641b5c9..ca2f663 100644 --- a/Redcraft.Core/Source/Public/CoreMinimal.h +++ b/Redcraft.Core/Source/Public/CoreMinimal.h @@ -1,4 +1,5 @@ #pragma once #include "CoreTypes.h" +#include "Templates/MemoryOps.h" #include "Misc/AssertionMacros.h" diff --git a/Redcraft.Core/Source/Public/HAL/Memory.inl b/Redcraft.Core/Source/Public/HAL/Memory.inl index 6081455..3dcd101 100644 --- a/Redcraft.Core/Source/Public/HAL/Memory.inl +++ b/Redcraft.Core/Source/Public/HAL/Memory.inl @@ -7,27 +7,27 @@ NS_REDCRAFT_BEGIN NS_BEGIN(Memory) -void* Memmove(void* Dest, const void* Src, size_t Count) +FORCEINLINE void* Memmove(void* Dest, const void* Src, size_t Count) { return std::memmove(Dest, Src, Count); } -int32 Memcmp(const void* Buf1, const void* Buf2, size_t Count) +FORCEINLINE int32 Memcmp(const void* Buf1, const void* Buf2, size_t Count) { return std::memcmp(Buf1, Buf2, Count); } -void Memset(void* Dest, uint8 ValueToSet, size_t Count) +FORCEINLINE void Memset(void* Dest, uint8 ValueToSet, size_t Count) { std::memset(Dest, ValueToSet, Count); } -void* Memzero(void* Dest, size_t Count) +FORCEINLINE void* Memzero(void* Dest, size_t Count) { return std::memset(Dest, 0, Count); } -void* Memcpy(void* Dest, const void* Src, size_t Count) +FORCEINLINE void* Memcpy(void* Dest, const void* Src, size_t Count) { return std::memcpy(Dest, Src, Count); } @@ -53,12 +53,12 @@ static FORCEINLINE void Memcpy(T& Dest, const T& Src) Memcpy(&Dest, &Src, sizeof(T)); } -void* SystemMalloc(size_t Count) +FORCEINLINE void* SystemMalloc(size_t Count) { return std::malloc(Count); } -void SystemFree(void* Ptr) +FORCEINLINE void SystemFree(void* Ptr) { std::free(Ptr); } diff --git a/Redcraft.Core/Source/Public/Templates/MemoryOps.h b/Redcraft.Core/Source/Public/Templates/MemoryOps.h new file mode 100644 index 0000000..a0ad064 --- /dev/null +++ b/Redcraft.Core/Source/Public/Templates/MemoryOps.h @@ -0,0 +1,35 @@ +#pragma once + +#include "CoreTypes.h" + +NS_REDCRAFT_BEGIN +NS_BEGIN(Memory) + +template +FORCEINLINE void DefaultConstructItems(void* Address, SizeType Count = 1); + +template +FORCEINLINE void DestructItems(ElementType* Element, SizeType Count = 1); + +template +FORCEINLINE void ConstructItems(void* Dest, const SourceElementType* Source, SizeType Count = 1); + +template +FORCEINLINE void CopyAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count = 1); + +template +FORCEINLINE void RelocateConstructItems(void* Dest, const SourceElementType* Source, SizeType Count = 1); + +template +FORCEINLINE void MoveConstructItems(void* Dest, const ElementType* Source, SizeType Count = 1); + +template +FORCEINLINE void MoveAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count = 1); + +template +FORCEINLINE bool CompareItems(const ElementType* A, const ElementType* B, SizeType Count = 1); + +NS_END(Memory) +NS_REDCRAFT_END + +#include "Templates/MemoryOps.inl" diff --git a/Redcraft.Core/Source/Public/Templates/MemoryOps.inl b/Redcraft.Core/Source/Public/Templates/MemoryOps.inl new file mode 100644 index 0000000..b7df516 --- /dev/null +++ b/Redcraft.Core/Source/Public/Templates/MemoryOps.inl @@ -0,0 +1,186 @@ +#include "HAL/Memory.h" +#include "Templates/TypeTraits.h" +#include "MemoryOps.h" + +NS_REDCRAFT_BEGIN +NS_BEGIN(Memory) + +NS_PRIVATE_BEGIN + +template +struct TCanBitwiseRelocate +{ + enum + { + Value = + TypeTraits::TOr< + TypeTraits::TIsSame, + TypeTraits::TAnd< + TypeTraits::TIsBitwiseConstructible, + TypeTraits::TIsTriviallyDestructible + > + >::Value + }; +}; + +NS_PRIVATE_END + +template +FORCEINLINE void DefaultConstructItems(void* Address, SizeType Count) +{ + if constexpr (TypeTraits::TIsZeroConstructType::Value) + { + Memory::Memset(Address, 0, sizeof(ElementType) * Count); + } + else + { + ElementType* Element = (ElementType*)Address; + while (Count) + { + new (Element) ElementType; + ++Element; + --Count; + } + } +} + +template +FORCEINLINE void DestructItems(ElementType* Element, SizeType Count) +{ + if constexpr (!TypeTraits::TIsTriviallyDestructible::Value) + { + while (Count) + { + typedef ElementType DestructItemsElementTypeTypedef; + + Element->DestructItemsElementTypeTypedef::~DestructItemsElementTypeTypedef(); + ++Element; + --Count; + } + } +} + +template +FORCEINLINE void ConstructItems(void* Dest, const SourceElementType* Source, SizeType Count) +{ + if constexpr (TypeTraits::TIsBitwiseConstructible::Value) + { + Memory::Memcpy(Dest, Source, sizeof(SourceElementType) * Count); + } + else + { + while (Count) + { + new (Dest) DestinationElementType(*Source); + ++(DestinationElementType*&)Dest; + ++Source; + --Count; + } + } +} + +template +FORCEINLINE void CopyAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count) +{ + if constexpr (TypeTraits::TIsTriviallyCopyAssignable::Value) + { + Memory::Memcpy(Dest, Source, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + *Dest = *Source; + ++Dest; + ++Source; + --Count; + } + } +} + +template +FORCEINLINE void RelocateConstructItems(void* Dest, const SourceElementType* Source, SizeType Count) +{ + if constexpr (NS_PRIVATE::TCanBitwiseRelocate::Value) + { + Memory::Memmove(Dest, Source, sizeof(SourceElementType) * Count); + } + else + { + while (Count) + { + typedef SourceElementType RelocateConstructItemsElementTypeTypedef; + + new (Dest) DestinationElementType(*Source); + ++(DestinationElementType*&)Dest; + (Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef(); + --Count; + } + } +} + +template +FORCEINLINE void MoveConstructItems(void* Dest, const ElementType* Source, SizeType Count) +{ + if constexpr (TypeTraits::TIsTriviallyCopyConstructible::Value) + { + Memory::Memmove(Dest, Source, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + new (Dest) ElementType((ElementType&&)*Source); + ++(ElementType*&)Dest; + ++Source; + --Count; + } + } +} + +template +FORCEINLINE void MoveAssignItems(ElementType* Dest, const ElementType* Source, SizeType Count) +{ + if constexpr (TypeTraits::TIsTriviallyCopyAssignable::Value) + { + Memory::Memmove(Dest, Source, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + *Dest = (ElementType&&)*Source; + ++Dest; + ++Source; + --Count; + } + } +} + +template +FORCEINLINE bool CompareItems(const ElementType* A, const ElementType* B, SizeType Count) +{ + if constexpr (TypeTraits::TCanBitwiseCompare::Value) + { + return !Memory::Memcmp(A, B, sizeof(ElementType) * Count); + } + else + { + while (Count) + { + if (!(*A == *B)) + { + return false; + } + + ++A; + ++B; + --Count; + } + + return true; + } +} + +NS_END(Memory) +NS_REDCRAFT_END diff --git a/Redcraft.Core/Source/Public/Templates/TypeTraits.h b/Redcraft.Core/Source/Public/Templates/TypeTraits.h index 18433eb..89e2429 100644 --- a/Redcraft.Core/Source/Public/Templates/TypeTraits.h +++ b/Redcraft.Core/Source/Public/Templates/TypeTraits.h @@ -7,7 +7,7 @@ NS_REDCRAFT_BEGIN NS_BEGIN(TypeTraits) -// Primary type categories +// Primary type categories. template struct TIsVoid { static constexpr bool Value = std::is_void_v; }; template struct TIsNullPointer { static constexpr bool Value = std::is_null_pointer_v; }; @@ -24,7 +24,7 @@ template struct TIsRValueReference { static constexpr bool Value template struct TIsMemberObjectPointer { static constexpr bool Value = std::is_member_object_pointer_v; }; template struct TIsMemberFunctionPointer { static constexpr bool Value = std::is_member_function_pointer_v; }; -// Composite type categories +// Composite type categories. template struct TIsFundamental { static constexpr bool Value = std::is_fundamental_v; }; template struct TIsArithmetic { static constexpr bool Value = std::is_arithmetic_v; }; @@ -34,7 +34,7 @@ template struct TIsCompound { static constexpr bool Value = st template struct TIsReference { static constexpr bool Value = std::is_reference_v; }; template struct TIsMemberPointer { static constexpr bool Value = std::is_member_pointer_v; }; -// Type properties +// Type properties. template struct TIsConst { static constexpr bool Value = std::is_const_v; }; template struct TIsVolatile { static constexpr bool Value = std::is_volatile_v; }; @@ -52,7 +52,7 @@ template struct TIsUnsigned { static constexpr template struct TIsBoundedArray { static constexpr bool Value = std::is_bounded_array_v; }; template struct TIsUnboundedArray { static constexpr bool Value = std::is_unbounded_array_v; }; -// Supported operations +// Supported operations. template struct TIsConstructible { static constexpr bool Value = std::is_constructible_v; }; template struct TIsTriviallyConstructible { static constexpr bool Value = std::is_trivially_constructible_v; }; @@ -74,12 +74,12 @@ template struct THasVirtualDestructor { static constexpr bool V template struct TIsSwappableWith { static constexpr bool Value = std::is_swappable_with_v; }; template struct TIsSwappable { static constexpr bool Value = std::is_swappable_v; }; -// Property queries +// Property queries. template struct TRank { static constexpr size_t Value = std::rank_v; }; template struct TExtent { static constexpr size_t Value = std::extent_v; }; -// Type relationships +// Type relationships. template struct TIsSame { static constexpr bool Value = std::is_same_v; }; template struct TIsBaseOf { static constexpr bool Value = std::is_base_of_v; }; @@ -87,7 +87,7 @@ template struct TIsConver template struct TIsInvocable { static constexpr bool Value = std::is_invocable_v; }; template struct TIsInvocableResult { static constexpr bool Value = std::is_invocable_r_v; }; -// Const-volatility specifiers +// Const-volatility specifiers. template struct TRemoveCV { typedef typename std::remove_cv_t Type; }; template struct TRemoveConst { typedef typename std::remove_const Type; }; @@ -96,28 +96,28 @@ template struct TAddCV { typedef typename std::add_cv template struct TAddConst { typedef typename std::add_const Type; }; template struct TAddVolatile { typedef typename std::add_volatile Type; }; -// References +// References. template struct TRemoveReference { typedef typename std::remove_reference_t Type; }; template struct TAddLValueReference { typedef typename std::add_lvalue_reference_t Type; }; template struct TAddRValueReference { typedef typename std::add_rvalue_reference_t Type; }; -// Pointers +// Pointers. template struct TRemovePointer { typedef typename std::remove_pointer_t Type; }; template struct TAddPointer { typedef typename std::add_pointer_t Type; }; -// Sign modifiers +// Sign modifiers. template struct TMakeSigned { typedef typename std::make_signed_t Type; }; template struct TMakeUnsigned { typedef typename std::make_unsigned_t Type; }; -// Arrays +// Arrays. template struct TRemoveExtent { typedef typename std::remove_extent_t Type; }; template struct TRemoveAllExtents { typedef typename std::remove_all_extents_t Type; }; -// Miscellaneous transformations +// Miscellaneous transformations. template struct TAlignedStorage { typedef typename std::aligned_storage_t Type; }; template struct TAlignedUnion { typedef typename std::aligned_union_t Type; }; @@ -128,22 +128,75 @@ template struct TCommonType { typedef template struct TUnderlyingType { typedef typename std::underlying_type_t Type; }; template struct TInvokeResult { typedef typename std::invoke_result_t Type; }; -// Operations on traits +// Operations on traits. -template struct TConstant { static constexpr T Value = InValue; }; -template struct TBoolConstant : TConstant { }; +template struct TConstant { static constexpr T Value = InValue; }; +template struct TBoolConstant : TConstant { }; -template struct TAnd; -template struct TAnd, RHS...> { static constexpr bool Value = TAnd::Value; }; -template struct TAnd, RHS...> { static constexpr bool Value = false; }; -template <> struct TAnd<> { static constexpr bool Value = true; }; +template struct TAnd; +template struct TAnd { static constexpr bool Value = LHS::Value && TAnd::Value; }; +template <> struct TAnd<> { static constexpr bool Value = true; }; -template struct TOr; -template struct TOr, RHS...> { static constexpr bool Value = true; }; -template struct TOr, RHS...> { static constexpr bool Value = TOr::Value; }; -template <> struct TOr<> { static constexpr bool Value = false; }; +template struct TOr; +template struct TOr { static constexpr bool Value = LHS::Value || TOr::Value; }; +template <> struct TOr<> { static constexpr bool Value = false; }; -template struct TNot { static constexpr bool Value = !Type::Value; }; +template struct TNot { static constexpr bool Value = !Type::Value; }; + +// Non-STD feature. + +template +struct TIsZeroConstructType +{ + static constexpr bool Value = TOr, TIsArithmetic, TIsPointer>::Value; +}; + +template +struct TCanBitwiseCompare +{ + static constexpr bool Value = TOr, TIsArithmetic, TIsPointer>::Value; +}; + +template +struct TIsBitwiseConstructible +{ + static_assert( + !TIsReference::Value && + !TIsReference::Value, + "TIsBitwiseConstructible is not designed to accept reference types"); + + static_assert( + TIsSame::Type>::Value && + TIsSame::Type>::Value, + "TIsBitwiseConstructible is not designed to accept qualified types"); + + static constexpr bool Value = false; +}; + +template +struct TIsBitwiseConstructible +{ + static constexpr bool Value = TIsTriviallyCopyConstructible::Value; +}; + +template +struct TIsBitwiseConstructible : TIsBitwiseConstructible +{ }; + +template +struct TIsBitwiseConstructible +{ + static constexpr bool Value = true; +}; + +template <> struct TIsBitwiseConstructible< uint8, int8> { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible< int8, uint8> { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible< int16, uint16> { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible< int32, uint32> { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible { static constexpr bool Value = true; }; +template <> struct TIsBitwiseConstructible< int64, uint64> { static constexpr bool Value = true; }; NS_END(TypeTraits) NS_REDCRAFT_END diff --git a/Redcraft.Debug/Source/Main.cpp b/Redcraft.Debug/Source/Main.cpp index 5544ed8..0a3fdf3 100644 --- a/Redcraft.Debug/Source/Main.cpp +++ b/Redcraft.Debug/Source/Main.cpp @@ -8,9 +8,52 @@ NS_STD_USING NS_REDCRAFT_USING +struct FTest +{ + FTest() { cout << "FTest()" << endl; } + ~FTest() { cout << "~FTest()" << endl; } + FTest(int32) { cout << "FTest(int32)" << endl; } + FTest(const FTest&) { cout << "FTest(const FTest&)" << endl; } + FTest(FTest&&) { cout << "FTest(FTest&&)" << endl; } + FTest& operator =(const FTest&) { cout << "FTest& operator =(const FTest&)" << endl; return *this; } + FTest& operator =(FTest&&) { cout << "FTest& operator =(FTest&&)" << endl; return *this; } + friend bool operator ==(const FTest&, const FTest&) { cout << "bool operator ==(const FTest&, const FTest&)" << endl; return true; } +}; + int main() { - check_no_entry(); + FTest* A = new FTest[2]; + FTest* B = new FTest[2]; + int32* C = new int32[2]; + int32* D = new int32[2]; + + cout << " --- " << endl; + + Memory::DefaultConstructItems(A, 2); + Memory::DestructItems(A, 2); + Memory::ConstructItems(A, C, 2); + Memory::CopyAssignItems(B, A, 2); + Memory::RelocateConstructItems(A, C, 2); + Memory::MoveConstructItems(B, A, 2); + Memory::MoveAssignItems(B, A, 2); + cout << (Memory::CompareItems(A, B, 2) ? "True" : "False") << endl; + + Memory::DefaultConstructItems(C, 2); + Memory::DestructItems(C, 2); + Memory::ConstructItems(C, D, 2); + Memory::CopyAssignItems(D, C, 2); + Memory::RelocateConstructItems(D, C, 2); + Memory::MoveConstructItems(D, C, 2); + Memory::MoveAssignItems(D, C, 2); + cout << (Memory::CompareItems(C, D, 2) ? "True" : "False") << endl; + + cout << " --- " << endl; + + delete[] A; + delete[] B; + delete[] C; + delete[] D; + cout << "Done!" << endl; return 0; }