feat(memory): add Memory/MemoryOperator.h and the corresponding testing
This commit is contained in:
parent
465ce882b9
commit
beaf5635ba
@ -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)
|
||||||
|
@ -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;
|
||||||
|
183
Redcraft.Utility/Source/Public/Memory/MemoryOperator.h
Normal file
183
Redcraft.Utility/Source/Public/Memory/MemoryOperator.h
Normal 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
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user