CyberEngineMkIII
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CYBBlock.cpp
Go to the documentation of this file.
1 #include "CYB.hpp"
3 
4 static_assert(sizeof(CYB::Engine::Memory::Block) ==
5 #ifdef DEBUG
6  32
7 #else
8  16
9 #endif
10  , "Block size has changed, check algorithms");
11 
12 CYB::Engine::Memory::Block::Block(const unsigned int ASpaceAvailable, const Block& ALeftBlock, const bool AFree) noexcept :
13 #ifdef DEBUG
14  FMagicHeader(MAGIC_HEADER),
15 #endif
16  FSizeAndFreeBit(InitializeData(ASpaceAvailable, AFree)),
17  FOffsetToPreviousBlock(CalculateOffset(ALeftBlock))
18 #ifdef DEBUG
19  ,FMagicFooter(MAGIC_FOOTER)
20 #endif
21 {
22  API::Assert::LessThanOrEqual<unsigned long long>(sizeof(Block), ASpaceAvailable);
23 }
24 
25 unsigned int CYB::Engine::Memory::Block::InitializeData(const unsigned int ASize, const bool AFree) noexcept {
26  const auto DataSize(static_cast<long long>(ASize - sizeof(Block)));
27  API::Assert::LessThanOrEqual<long long>(0, DataSize);
28  API::Assert::LessThanOrEqual<long long>(DataSize, std::numeric_limits<int>().max());
29  if(AFree)
30  return static_cast<unsigned int>(DataSize) | 1U << 31;
31  return static_cast<unsigned int>(DataSize) & ~(1U << 31);
32 }
33 
34 unsigned int CYB::Engine::Memory::Block::CalculateOffset(const Block& ABlock) noexcept {
35  API::Assert::LessThanOrEqual<const Block*>(&ABlock, this);
36  const auto Result(reinterpret_cast<byte*>(this) - reinterpret_cast<const byte*>(&ABlock));
37  API::Assert::LessThanOrEqual<long long>(Result, std::numeric_limits<unsigned int>().max());
38  return static_cast<unsigned int>(Result);
39 }
40 
41 unsigned int CYB::Engine::Memory::Block::Size(void) const noexcept {
42  const auto Result(FSizeAndFreeBit & ~(1U << 31));
43  API::Assert::LessThan(Result, static_cast<unsigned int>(std::numeric_limits<int>::max()));
44  return Result;
45 }
46 
47 bool CYB::Engine::Memory::Block::IsFree(void) const noexcept {
48  return (FSizeAndFreeBit >> 31) & 1;
49 }
50 
51 bool CYB::Engine::Memory::Block::IsLargeBlock(void) const noexcept {
52  return IsFree() && Size() == 0;
53 }
54 
56  return this + 1;
57 }
58 
60  Block& TheBlock(*reinterpret_cast<Block*>(static_cast<byte*>(AData) - sizeof(Block)));
61  TheBlock.Validate();
62  return TheBlock;
63 }
64 
66  if (FOffsetToPreviousBlock == 0)
67  return nullptr;
68  return reinterpret_cast<Block*>(reinterpret_cast<byte*>(this) - FOffsetToPreviousBlock);
69 }
70 
72  API::Assert::False(IsLargeBlock());
73  return *reinterpret_cast<Block*>(static_cast<byte*>(GetData()) + Size());
74 }
75 
77  API::Assert::False(IsLargeBlock());
78  return *reinterpret_cast<const Block*>(reinterpret_cast<const byte*>(this) + sizeof(Block) + Size());
79 }
80 void CYB::Engine::Memory::Block::SetSize(const unsigned int ANewSize) noexcept {
81  API::Assert::LessThan(ANewSize, static_cast<unsigned int>(std::numeric_limits<int>::max()));
82  FSizeAndFreeBit = FSizeAndFreeBit - Size() + ANewSize;
83 }
84 void CYB::Engine::Memory::Block::SetFree(const bool ANewFree) noexcept {
85  if(ANewFree)
86  FSizeAndFreeBit |= 1U << 31;
87  else
88  FSizeAndFreeBit &= ~(1U << 31);
89 }
90 
92 #ifdef DEBUG
93  API::Assert::Equal<unsigned long long>(FMagicHeader, MAGIC_HEADER);
94  API::Assert::Equal<unsigned long long>(FMagicFooter, MAGIC_FOOTER);
95 #endif
96 }
97 
98 CYB::Engine::Memory::Block& CYB::Engine::Memory::Block::Splice(const unsigned int ASizeToKeep) noexcept {
99  API::Assert::False(IsLargeBlock());
100  API::Assert::LessThan(ASizeToKeep, static_cast<unsigned int>(std::numeric_limits<int>::max()));
101  const auto NewBlockAmount(Size() - ASizeToKeep);
102  API::Assert::LessThan<unsigned long long>(sizeof(Block), NewBlockAmount);
103  SetSize(ASizeToKeep);
104  auto& Result(*API::Interop::Allocator::InPlaceAllocation<Block>(static_cast<byte*>(GetData()) + ASizeToKeep, static_cast<unsigned int>(NewBlockAmount), *this, true));
105  Result.RightBlock().FOffsetToPreviousBlock = Result.RightBlock().CalculateOffset(Result);
106  return Result;
107 }
108 
110  API::Assert::False(IsLargeBlock());
111  API::Assert::NotEqual<Block*>(LeftBlock(), nullptr);
112  API::Assert::Equal(&LeftBlock()->RightBlock(), this);
113  auto& LBlock(*LeftBlock());
114  const auto NewSize(LBlock.Size() + Size() + sizeof(Block));
115  API::Assert::LessThan<unsigned long long>(NewSize, static_cast<unsigned long long>(std::numeric_limits<int>::max()));
116  LBlock.SetSize(static_cast<unsigned int>(NewSize));
117  LBlock.RightBlock().FOffsetToPreviousBlock = LBlock.RightBlock().CalculateOffset(LBlock);
118  return LBlock;
119 }
bool IsFree(void) const noexcept
Check if this Block is free.
Definition: CYBBlock.cpp:47
unsigned char byte
It's a byte, 8 bits, etc...
Definition: Types.hpp:4
Block & EatLeftBlock(void) noexcept
Merge size and header into the size of the Block to the left. Does not modify free lists...
Definition: CYBBlock.cpp:109
#define DEBUG
Should be defined or not by user before all inclusions of CyberEngine.hpp. Enables engine debugging l...
Block & RightBlock(void) noexcept
Get the block to the right of this Block.
Definition: CYBBlock.cpp:71
Block(const unsigned int ASpaceAvailable, const Block &ALeftBlock, const bool AFree) noexcept
Create a Block. Should be used with operator new in a memory location at least ASpaceAvailable large...
Definition: CYBBlock.cpp:12
void SetFree(const bool ANewFree) noexcept
Set the Block's free state.
Definition: CYBBlock.cpp:84
Block & Splice(const unsigned int ASizeToKeep) noexcept
Separate this block into two.
Definition: CYBBlock.cpp:98
static void LessThan(const AType &ALHS, const AType &ARHS) noexcept
Less than assertion function. May not be evaluated.
void * GetData(void) noexcept
Get the data portion of the memory owned by this Block.
Definition: CYBBlock.cpp:55
static unsigned int InitializeData(const unsigned int ASize, const bool AFree) noexcept
Returns the Size and Free integer given a size and free state.
Definition: CYBBlock.cpp:25
void SetSize(const unsigned int ANewSize) noexcept
Set the Block's size.
Definition: CYBBlock.cpp:80
static Block & FromData(void *const AData)
Retrieves a reference to a Block given it's data pointer.
Definition: CYBBlock.cpp:59
bool IsLargeBlock(void) const noexcept
Check if this Block is a LargeBlock.
Definition: CYBBlock.cpp:51
static void Equal(const AType &ALHS, const AType &ARHS) noexcept
Equivalence assertion function. May not be evaluated.
unsigned int CalculateOffset(const Block &ABlock) noexcept
Calculate the byte offset to another Block.
Definition: CYBBlock.cpp:34
Precompiled header for inter-engine operations.
static void False(const bool AExpression) noexcept
False assertion function. AExpression should always be evaluated.
void Validate(void) const
Checks the validity of a Block HCFs if invalid. Has no effect outside of DEBUG mode.
Definition: CYBBlock.cpp:91
Block * LeftBlock(void) noexcept
Get the block to the left of this Block.
Definition: CYBBlock.cpp:65
A unit of memory allocation.
Definition: CYBBlock.hpp:7
unsigned int Size(void) const noexcept
Get the size of the Block.
Definition: CYBBlock.cpp:41
unsigned int FSizeAndFreeBit
The size of this block and it's free bit.
Definition: CYBBlock.hpp:21