Skip to content

Commit f150c05

Browse files
committed
fix: make allocators cross-platform
- Use platform-specific aligned allocation (Windows vs POSIX) - Fix malloc.h include for macOS (use cstdlib instead) - Suppress unused variable warnings in assertions - All platforms now build successfully Signed-off-by: NotKeira <github.rxs06@accounts.keira.boo>
1 parent c95141c commit f150c05

6 files changed

Lines changed: 114 additions & 69 deletions

File tree

.idea/dictionaries/project.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/freelist_allocator.cpp

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
#include "freelist_allocator.h"
2-
#include <malloc.h>
32
#include <cassert>
4-
// #include <algorithm>
3+
#include <algorithm>
4+
5+
#ifdef _WIN32
6+
#include <malloc.h>
7+
#else
8+
#include <cstdlib>
9+
#endif
510

611
namespace fast_alloc
712
{
8-
FreeListAllocator::FreeListAllocator(std::size_t size, FreeListStrategy strategy)
13+
FreeListAllocator::FreeListAllocator(const std::size_t size, const FreeListStrategy strategy)
914
: size_(size)
1015
, used_memory_(0)
1116
, num_allocations_(0)
@@ -15,7 +20,11 @@ namespace fast_alloc
1520
{
1621
assert(size > sizeof(FreeBlock) && "Size must be larger than FreeBlock");
1722

23+
#ifdef _WIN32
1824
memory_ = _aligned_malloc(size_, alignof(std::max_align_t));
25+
#else
26+
memory_ = std::aligned_alloc(alignof(std::max_align_t), size_);
27+
#endif
1928
assert(memory_ && "Failed to allocate memory");
2029

2130
// Initialise with one large free block
@@ -28,7 +37,11 @@ namespace fast_alloc
2837
{
2938
if (memory_)
3039
{
40+
#ifdef _WIN32
3141
_aligned_free(memory_);
42+
#else
43+
std::free(memory_);
44+
#endif
3245
}
3346
}
3447

@@ -53,7 +66,11 @@ namespace fast_alloc
5366
{
5467
if (memory_)
5568
{
69+
#ifdef _WIN32
5670
_aligned_free(memory_);
71+
#else
72+
std::free(memory_);
73+
#endif
5774
}
5875

5976
size_ = other.size_;
@@ -72,7 +89,7 @@ namespace fast_alloc
7289
return *this;
7390
}
7491

75-
void* FreeListAllocator::allocate(std::size_t size, std::size_t alignment)
92+
void* FreeListAllocator::allocate(const std::size_t size, const std::size_t alignment)
7693
{
7794
assert(size > 0 && "Allocation size must be greater than zero");
7895
assert(memory_ && "Allocator not initialised");
@@ -87,13 +104,7 @@ namespace fast_alloc
87104
// Search for suitable block
88105
while (current_block)
89106
{
90-
std::size_t adjustment = 0;
91-
// std::size_t aligned_address = align_forward_with_header(
92-
// reinterpret_cast<std::size_t>(current_block),
93-
// alignment,
94-
// sizeof(AllocationHeader),
95-
// adjustment
96-
// );
107+
constexpr std::size_t adjustment = 0;
97108

98109
if (const std::size_t total_size = size + adjustment; current_block->size >= total_size)
99110
{
@@ -104,9 +115,9 @@ namespace fast_alloc
104115
best_prev = prev_block;
105116
break;
106117
}
107-
else if (strategy_ == FreeListStrategy::BestFit)
118+
if (strategy_ == FreeListStrategy::BestFit)
108119
{
109-
// Use best fit - find smallest suitable block
120+
// Use best fit - find the smallest suitable block
110121
if (current_block->size < best_size)
111122
{
112123
best_size = current_block->size;
@@ -127,19 +138,19 @@ namespace fast_alloc
127138

128139
// Calculate adjustment again for the selected block
129140
std::size_t adjustment = 0;
130-
std::size_t aligned_address = align_forward_with_header(
141+
const std::size_t aligned_address = align_forward_with_header(
131142
reinterpret_cast<std::size_t>(best_block),
132143
alignment,
133144
sizeof(AllocationHeader),
134145
adjustment
135146
);
136147

137-
std::size_t total_size = size + adjustment;
148+
const std::size_t total_size = size + adjustment;
138149

139150
// If remaining space is large enough, split the block
140151
if (best_block->size - total_size > sizeof(FreeBlock))
141152
{
142-
FreeBlock* new_block = reinterpret_cast<FreeBlock*>(
153+
auto* new_block = reinterpret_cast<FreeBlock*>(
143154
reinterpret_cast<std::size_t>(best_block) + total_size
144155
);
145156
new_block->size = best_block->size - total_size;
@@ -168,7 +179,7 @@ namespace fast_alloc
168179
}
169180

170181
// Write allocation header
171-
AllocationHeader* header = reinterpret_cast<AllocationHeader*>(
182+
auto* header = reinterpret_cast<AllocationHeader*>(
172183
aligned_address - sizeof(AllocationHeader)
173184
);
174185
header->size = total_size;
@@ -191,16 +202,16 @@ namespace fast_alloc
191202
assert(num_allocations_ > 0 && "Deallocating from empty allocator");
192203

193204
// Get allocation header
194-
std::size_t block_address = reinterpret_cast<std::size_t>(ptr);
195-
AllocationHeader* header = reinterpret_cast<AllocationHeader*>(
205+
const auto block_address = reinterpret_cast<std::size_t>(ptr);
206+
const auto* header = reinterpret_cast<AllocationHeader*>(
196207
block_address - sizeof(AllocationHeader)
197208
);
198209

199-
std::size_t block_start = block_address - header->adjustment;
200-
std::size_t block_size = header->size;
210+
const std::size_t block_start = block_address - header->adjustment;
211+
const std::size_t block_size = header->size;
201212

202213
// Create new free block
203-
FreeBlock* new_block = reinterpret_cast<FreeBlock*>(block_start);
214+
auto* new_block = reinterpret_cast<FreeBlock*>(block_start);
204215
new_block->size = block_size;
205216
new_block->next = nullptr;
206217

@@ -241,10 +252,9 @@ namespace fast_alloc
241252
// Merge with next block if adjacent
242253
if (current->next)
243254
{
244-
std::size_t current_end = reinterpret_cast<std::size_t>(current) + current->size;
245-
std::size_t next_start = reinterpret_cast<std::size_t>(current->next);
255+
const std::size_t current_end = reinterpret_cast<std::size_t>(current) + current->size;
246256

247-
if (current_end == next_start)
257+
if (const auto next_start = reinterpret_cast<std::size_t>(current->next); current_end == next_start)
248258
{
249259
current->size += current->next->size;
250260
current->next = current->next->next;
@@ -254,10 +264,9 @@ namespace fast_alloc
254264
// Merge with previous block if adjacent
255265
if (previous)
256266
{
257-
std::size_t prev_end = reinterpret_cast<std::size_t>(previous) + previous->size;
258-
std::size_t current_start = reinterpret_cast<std::size_t>(current);
267+
const std::size_t prev_end = reinterpret_cast<std::size_t>(previous) + previous->size;
259268

260-
if (prev_end == current_start)
269+
if (const auto current_start = reinterpret_cast<std::size_t>(current); prev_end == current_start)
261270
{
262271
previous->size += current->size;
263272
previous->next = current->next;
@@ -266,18 +275,17 @@ namespace fast_alloc
266275
}
267276

268277
std::size_t FreeListAllocator::align_forward_with_header(
269-
std::size_t address,
270-
std::size_t alignment,
271-
std::size_t header_size,
278+
const std::size_t address,
279+
const std::size_t alignment,
280+
const std::size_t header_size,
272281
std::size_t& adjustment
273-
) const noexcept
282+
) noexcept
274283
{
275284
assert((alignment & (alignment - 1)) == 0 && "Alignment must be power of 2");
276285

277286
std::size_t aligned_address = address + header_size;
278287

279-
std::size_t modulo = aligned_address & (alignment - 1);
280-
if (modulo != 0)
288+
if (const std::size_t modulo = aligned_address & (alignment - 1); modulo != 0)
281289
{
282290
aligned_address += alignment - modulo;
283291
}
@@ -286,4 +294,4 @@ namespace fast_alloc
286294

287295
return aligned_address;
288296
}
289-
} // namespace fast_alloc
297+
} // namespace fast_alloc

src/freelist_allocator.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace fast_alloc
88
enum class FreeListStrategy
99
{
1010
FirstFit, // Find first block that fits
11-
BestFit // Find smallest block that fits
11+
BestFit // Find the smallest block that fits
1212
};
1313

1414
class FreeListAllocator
@@ -53,12 +53,12 @@ namespace fast_alloc
5353
void* memory_;
5454
FreeBlock* free_blocks_;
5555

56-
void coalescence(FreeBlock* previous, FreeBlock* current);
57-
[[nodiscard]] std::size_t align_forward_with_header(
56+
static void coalescence(FreeBlock* previous, FreeBlock* current);
57+
static std::size_t align_forward_with_header(
5858
std::size_t address,
5959
std::size_t alignment,
6060
std::size_t header_size,
6161
std::size_t& adjustment
62-
) const noexcept;
62+
) noexcept;
6363
};
64-
} // namespace fast_alloc
64+
} // namespace fast_alloc

src/pool_allocator.cpp

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,41 @@
11
#include "pool_allocator.h"
2-
#include <malloc.h>
2+
33
#include <cassert>
44
#include <cstring>
55

6+
#ifdef _WIN32
7+
#include <malloc.h>
8+
#else
9+
#include <cstdlib>
10+
#endif
11+
612
namespace fast_alloc
713
{
8-
/**
9-
*
10-
* @param block_size
11-
* @param block_count
12-
*/
13-
PoolAllocator::PoolAllocator(std::size_t block_size, std::size_t block_count) :
14-
block_size_(block_size), block_count_(block_count), allocated_count_(0), memory_(nullptr), free_list_(nullptr)
14+
PoolAllocator::PoolAllocator(std::size_t block_size, std::size_t block_count)
15+
: block_size_(block_size)
16+
, block_count_(block_count)
17+
, allocated_count_(0)
18+
, memory_(nullptr)
19+
, free_list_(nullptr)
1520
{
1621
assert(block_size >= sizeof(void*) && "Block size must be at least pointer size");
1722
assert(block_count > 0 && "Block count must be greater than zero");
1823

1924
// Allocate the memory pool
25+
#ifdef _WIN32
2026
memory_ = _aligned_malloc(block_size_ * block_count_, alignof(std::max_align_t));
27+
#else
28+
memory_ = std::aligned_alloc(alignof(std::max_align_t), block_size_ * block_count_);
29+
#endif
2130
assert(memory_ && "Failed to allocate memory pool");
2231

2332
// Initialise free list - each block points to the next
24-
std::byte* block = static_cast<std::byte*>(memory_);
33+
auto* block = static_cast<std::byte*>(memory_);
2534
free_list_ = block;
2635

2736
for (std::size_t i = 0; i < block_count_ - 1; ++i)
2837
{
29-
void** current = reinterpret_cast<void**>(block);
38+
const auto current = reinterpret_cast<void**>(block);
3039
block += block_size_;
3140
*current = block;
3241
}
@@ -40,7 +49,11 @@ namespace fast_alloc
4049
{
4150
if (memory_)
4251
{
52+
#ifdef _WIN32
4353
_aligned_free(memory_);
54+
#else
55+
std::free(memory_);
56+
#endif
4457
}
4558
}
4659

@@ -62,7 +75,11 @@ namespace fast_alloc
6275
{
6376
if (memory_)
6477
{
78+
#ifdef _WIN32
6579
_aligned_free(memory_);
80+
#else
81+
std::free(memory_);
82+
#endif
6683
}
6784

6885
block_size_ = other.block_size_;
@@ -108,4 +125,4 @@ namespace fast_alloc
108125
free_list_ = ptr;
109126
--allocated_count_;
110127
}
111-
} // namespace fast_alloc
128+
} // namespace fast_alloc

0 commit comments

Comments
 (0)