1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#include "memheap.h"
4#include <base/system.h>
5#include <cstdint>
6#include <cstdlib>
7
8// allocates a new chunk to be used
9void CHeap::NewChunk()
10{
11 // the chunk structure is located in the beginning of the chunk
12 // init it and return the chunk
13 CChunk *pChunk = static_cast<CChunk *>(malloc(size: sizeof(CChunk) + CHUNK_SIZE));
14 if(!pChunk)
15 return;
16 pChunk->m_pMemory = static_cast<char *>(static_cast<void *>(pChunk + 1));
17 pChunk->m_pCurrent = pChunk->m_pMemory;
18 pChunk->m_pEnd = pChunk->m_pMemory + CHUNK_SIZE;
19 pChunk->m_pNext = nullptr;
20
21 pChunk->m_pNext = m_pCurrent;
22 m_pCurrent = pChunk;
23}
24
25//****************
26void *CHeap::AllocateFromChunk(unsigned int Size, unsigned Alignment)
27{
28 size_t Offset = reinterpret_cast<uintptr_t>(m_pCurrent->m_pCurrent) % Alignment;
29 if(Offset)
30 Offset = Alignment - Offset;
31
32 // check if we need can fit the allocation
33 if(m_pCurrent->m_pCurrent + Offset + Size > m_pCurrent->m_pEnd)
34 return nullptr;
35
36 // get memory and move the pointer forward
37 char *pMem = m_pCurrent->m_pCurrent + Offset;
38 m_pCurrent->m_pCurrent += Offset + Size;
39 return pMem;
40}
41
42// creates a heap
43CHeap::CHeap()
44{
45 m_pCurrent = nullptr;
46 Reset();
47}
48
49CHeap::~CHeap()
50{
51 Clear();
52}
53
54void CHeap::Reset()
55{
56 Clear();
57 NewChunk();
58}
59
60// destroys the heap
61void CHeap::Clear()
62{
63 while(m_pCurrent)
64 {
65 CChunk *pNext = m_pCurrent->m_pNext;
66 free(ptr: m_pCurrent);
67 m_pCurrent = pNext;
68 }
69}
70
71//
72void *CHeap::Allocate(unsigned Size, unsigned Alignment)
73{
74 // try to allocate from current chunk
75 void *pMem = AllocateFromChunk(Size, Alignment);
76 if(!pMem)
77 {
78 // allocate new chunk and add it to the heap
79 NewChunk();
80
81 // try to allocate again
82 pMem = AllocateFromChunk(Size, Alignment);
83 }
84
85 return pMem;
86}
87
88const char *CHeap::StoreString(const char *pSrc)
89{
90 const int Size = str_length(str: pSrc) + 1;
91 char *pMem = static_cast<char *>(Allocate(Size));
92 str_copy(dst: pMem, src: pSrc, dst_size: Size);
93 return pMem;
94}
95