feat(memory): add Memory/MemoryOperator.h and the corresponding testing

This commit is contained in:
_Redstone_c_ 2022-03-19 16:05:47 +08:00
parent 465ce882b9
commit beaf5635ba
4 changed files with 260 additions and 13 deletions

View File

@ -2,6 +2,7 @@
#include "Memory/Memory.h" #include "Memory/Memory.h"
#include "Memory/Alignment.h" #include "Memory/Alignment.h"
#include "Memory/MemoryOperator.h"
#include "Miscellaneous/AssertionMacros.h" #include "Miscellaneous/AssertionMacros.h"
NAMESPACE_REDCRAFT_BEGIN NAMESPACE_REDCRAFT_BEGIN
@ -15,6 +16,7 @@ void TestMemory()
TestAlignment(); TestAlignment();
TestMemoryBuffer(); TestMemoryBuffer();
TestMemoryMalloc(); TestMemoryMalloc();
TestMemoryOperator();
} }
void TestAlignment() void TestAlignment()
@ -139,6 +141,67 @@ void TestMemoryMalloc()
} }
NAMESPACE_UNNAMED_BEGIN
struct FTracker
{
static int32 Status;
FTracker() { always_check(Status == 0); Status = -1; }
FTracker(const FTracker&) { always_check(Status == 1); Status = -1; }
FTracker(FTracker&&) { always_check(Status == 2); Status = -1; }
~FTracker() { always_check(Status == 3); Status = -1; }
FTracker& operator=(const FTracker&) { always_check(Status == 4); Status = -1; return *this; }
FTracker& operator=(FTracker&&) { always_check(Status == 5); Status = -1; return *this; }
friend bool operator==(const FTracker&, const FTracker&) { always_check(Status == 6); Status = -1; return true; }
};
int32 FTracker::Status = -1;
NAMESPACE_UNNAMED_END
void TestMemoryOperator()
{
FTracker* PtrA = reinterpret_cast<FTracker*>(Memory::Malloc(sizeof(FTracker)));
FTracker* PtrB = reinterpret_cast<FTracker*>(Memory::Malloc(sizeof(FTracker)));
FTracker::Status = 0;
Memory::DefaultConstruct(PtrA);
always_check(FTracker::Status == -1);
FTracker::Status = 1;
Memory::Construct(PtrA, PtrB);
always_check(FTracker::Status == -1);
FTracker::Status = 2;
Memory::MoveConstruct(PtrA, PtrB);
always_check(FTracker::Status == -1);
FTracker::Status = -1;
Memory::RelocateConstruct(PtrA, PtrB);
always_check(FTracker::Status == -1);
FTracker::Status = 3;
Memory::Destruct(PtrA);
always_check(FTracker::Status == -1);
FTracker::Status = 4;
Memory::CopyAssign(PtrA, PtrB);
always_check(FTracker::Status == -1);
FTracker::Status = 5;
Memory::MoveAssign(PtrA, PtrB);
always_check(FTracker::Status == -1);
FTracker::Status = 6;
const bool bResult = Memory::Compare(PtrA, PtrB);
always_check(bResult);
always_check(FTracker::Status == -1);
Memory::Free(PtrA);
Memory::Free(PtrB);
}
NAMESPACE_END(Testing) NAMESPACE_END(Testing)
NAMESPACE_MODULE_END(Utility) NAMESPACE_MODULE_END(Utility)

View File

@ -17,7 +17,7 @@ void TestMiscellaneous()
TestTypeInfo(); TestTypeInfo();
} }
NAMESPACE_PRIVATE_BEGIN NAMESPACE_UNNAMED_BEGIN
void TestNoEntry() void TestNoEntry()
{ {
@ -47,7 +47,7 @@ void TestUnimplemented()
always_unimplemented(); always_unimplemented();
} }
NAMESPACE_PRIVATE_END NAMESPACE_UNNAMED_END
void TestAssertionMacros() void TestAssertionMacros()
{ {
@ -61,16 +61,16 @@ void TestAssertionMacros()
always_checkf(true, "True!"); always_checkf(true, "True!");
//always_checkf(false, "False!"); //always_checkf(false, "False!");
//NAMESPACE_PRIVATE::TestNoEntry(); //TestNoEntry();
NAMESPACE_PRIVATE::TestNoReentry(); TestNoReentry();
//NAMESPACE_PRIVATE::TestNoReentry(); //TestNoReentry();
NAMESPACE_PRIVATE::TestNoRecursion(0); TestNoRecursion(0);
NAMESPACE_PRIVATE::TestNoRecursion(0); TestNoRecursion(0);
//NAMESPACE_PRIVATE::TestNoRecursion(1); //TestNoRecursion(1);
//NAMESPACE_PRIVATE::TestUnimplemented(); //TestUnimplemented();
verify(true); verify(true);
//verify(false); //verify(false);
@ -209,12 +209,12 @@ void TestCompare()
} }
NAMESPACE_PRIVATE_BEGIN NAMESPACE_UNNAMED_BEGIN
template <typename...> template <typename...>
struct TTestTemplateType { }; struct TTestTemplateType { };
NAMESPACE_PRIVATE_END NAMESPACE_UNNAMED_END
void TestTypeInfo() void TestTypeInfo()
{ {
@ -224,8 +224,8 @@ void TestTypeInfo()
always_check(TempA == TempB); always_check(TempA == TempB);
always_check(TempA == Typeid(void)); always_check(TempA == Typeid(void));
FTypeInfo TempC(Typeid(NAMESPACE_PRIVATE::TTestTemplateType<int8, int16>)); FTypeInfo TempC(Typeid(TTestTemplateType<int8, int16>));
FTypeInfo TempD = Typeid(NAMESPACE_PRIVATE::TTestTemplateType<int8, int32>); FTypeInfo TempD = Typeid(TTestTemplateType<int8, int32>);
FTypeInfo TempE, TempF; FTypeInfo TempE, TempF;
TempE = TempC; TempE = TempC;

View File

@ -0,0 +1,183 @@
#pragma once
#include "CoreTypes.h"
#include "Templates/Utility.h"
#include "Concepts/Comparable.h"
#include "TypeTraits/TypeTraits.h"
NAMESPACE_REDCRAFT_BEGIN
NAMESPACE_MODULE_BEGIN(Redcraft)
NAMESPACE_MODULE_BEGIN(Utility)
NAMESPACE_BEGIN(Memory)
template <typename ElementType, typename SizeType = int32>
requires (TIsDefaultConstructible<ElementType>::Value || TIsZeroConstructible<ElementType>::Value)
FORCEINLINE void DefaultConstruct(ElementType* Address, SizeType Count = 1)
{
if constexpr (TIsZeroConstructible<ElementType>::Value)
{
Memory::Memset(Address, 0, sizeof(ElementType) * Count);
}
else
{
ElementType* Element = (ElementType*)Address;
while (Count)
{
new (Element) ElementType;
++Element;
--Count;
}
}
}
template <typename DestinationElementType, typename SourceElementType, typename SizeType = int32>
requires (TIsConstructible<DestinationElementType, const SourceElementType&>::Value || TIsBitwiseConstructible<DestinationElementType, const SourceElementType&>::Value)
FORCEINLINE void Construct(DestinationElementType* Destination, const SourceElementType* Source, SizeType Count = 1)
{
if constexpr (TIsBitwiseConstructible<DestinationElementType, const SourceElementType>::Value)
{
Memory::Memcpy(Destination, Source, sizeof(SourceElementType) * Count);
}
else
{
while (Count)
{
new (Destination) DestinationElementType(*Source);
++(DestinationElementType*&)Destination;
++Source;
--Count;
}
}
}
template <typename ElementType, typename SizeType = int32>
requires (TIsMoveConstructible<ElementType>::Value)
FORCEINLINE void MoveConstruct(ElementType* Destination, ElementType* Source, SizeType Count = 1)
{
if constexpr (TIsTriviallyMoveConstructible<ElementType>::Value)
{
Memory::Memmove(Destination, Source, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
new (Destination) ElementType(MoveTemp(*Source));
++(ElementType*&)Destination;
++Source;
--Count;
}
}
}
template <typename DestinationElementType, typename SourceElementType, typename SizeType = int32>
requires ((TIsConstructible<DestinationElementType, SourceElementType&&>::Value && TIsDestructible<SourceElementType>::Value) || TIsBitwiseRelocatable<DestinationElementType, SourceElementType>::Value)
FORCEINLINE void RelocateConstruct(DestinationElementType* Destination, SourceElementType* Source, SizeType Count = 1)
{
if constexpr (TIsBitwiseRelocatable<DestinationElementType, SourceElementType>::Value)
{
Memory::Memmove(Destination, Source, sizeof(SourceElementType) * Count);
}
else
{
while (Count)
{
typedef SourceElementType RelocateConstructItemsElementTypeTypedef;
new (Destination) DestinationElementType(MoveTemp(*Source));
++(DestinationElementType*&)Destination;
(Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef();
--Count;
}
}
}
template <typename ElementType, typename SizeType = int32>
requires (TIsDestructible<ElementType>::Value)
FORCEINLINE void Destruct(ElementType* Element, SizeType Count = 1)
{
if constexpr (!TIsTriviallyDestructible<ElementType>::Value)
{
while (Count)
{
typedef ElementType DestructItemsElementTypeTypedef;
Element->DestructItemsElementTypeTypedef::~DestructItemsElementTypeTypedef();
++Element;
--Count;
}
}
}
template <typename ElementType, typename SizeType = int32>
requires (TIsCopyAssignable<ElementType>::Value)
FORCEINLINE void CopyAssign(ElementType* Destination, const ElementType* Source, SizeType Count = 1)
{
if constexpr (TIsTriviallyCopyAssignable<ElementType>::Value)
{
Memory::Memcpy(Destination, Source, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
*Destination = *Source;
++Destination;
++Source;
--Count;
}
}
}
template <typename ElementType, typename SizeType = int32>
requires (TIsMoveAssignable<ElementType>::Value)
FORCEINLINE void MoveAssign(ElementType* Destination, ElementType* Source, SizeType Count = 1)
{
if constexpr (TIsTriviallyCopyConstructible<ElementType>::Value)
{
Memory::Memmove(Destination, Source, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
*Destination = MoveTemp(*Source);
++(ElementType*&)Destination;
++Source;
--Count;
}
}
}
template <typename ElementType, typename SizeType = int32>
requires (CEqualityComparable<ElementType> || TIsBitwiseComparable<ElementType>::Value)
FORCEINLINE bool Compare(const ElementType* LHS, const ElementType* RHS, SizeType Count = 1)
{
if constexpr (TIsBitwiseComparable<ElementType>::Value)
{
return !Memory::Memcmp(LHS, RHS, sizeof(ElementType) * Count);
}
else
{
while (Count)
{
if (!(*LHS == *RHS))
{
return false;
}
++LHS;
++RHS;
--Count;
}
return true;
}
}
NAMESPACE_END(Memory)
NAMESPACE_MODULE_END(Utility)
NAMESPACE_MODULE_END(Redcraft)
NAMESPACE_REDCRAFT_END

View File

@ -12,6 +12,7 @@ REDCRAFTUTILITY_API void TestMemory();
REDCRAFTUTILITY_API void TestAlignment(); REDCRAFTUTILITY_API void TestAlignment();
REDCRAFTUTILITY_API void TestMemoryBuffer(); REDCRAFTUTILITY_API void TestMemoryBuffer();
REDCRAFTUTILITY_API void TestMemoryMalloc(); REDCRAFTUTILITY_API void TestMemoryMalloc();
REDCRAFTUTILITY_API void TestMemoryOperator();
NAMESPACE_END(Testing) NAMESPACE_END(Testing)