openMSX
monotonic_allocator.hh
Go to the documentation of this file.
1#ifndef MEMORY_RESOURCE
2#define MEMORY_RESOURCE
3
4#include <algorithm>
5#include <cassert>
6#include <cstddef>
7#include <cstdlib>
8#include <memory>
9#include <new>
10
11// A minimal re-implementation of std::monotonic_buffer_resource.
12// Because libc++ doesn't have this yet, even though it's part of c++17.
13
15{
16public:
18
19 explicit monotonic_allocator(size_t initialSize)
20 : nextSize(initialSize)
21 {
22 assert(initialSize != 0);
23 }
24
25 monotonic_allocator(void* buffer, size_t bufferSize)
26 : current(buffer)
27 , available(bufferSize)
28 , nextSize(2 * bufferSize)
29 {
30 assert(buffer || bufferSize == 0);
31 }
32
37
39 {
40 void* p = head;
41 while (p) {
42 void* next = *static_cast<void**>(p);
43 free(p);
44 p = next;
45 }
46 }
47
48 [[nodiscard]] void* allocate(size_t bytes, size_t alignment)
49 {
50 assert(alignment <= alignof(max_align_t));
51
52 if (bytes == 0) bytes = 1;
53 void* p = std::align(alignment, bytes, current, available);
54 if (!p) {
55 newBuffer(bytes);
56 p = current;
57 }
58 current = static_cast<char*>(current) + bytes;
59 available -= bytes;
60 return p;
61 }
62
63private:
64 void newBuffer(size_t bytes)
65 {
66 size_t n = std::max(nextSize, bytes);
67 void* newBuf = malloc(n + sizeof(void*));
68 if (!newBuf) {
69 throw std::bad_alloc();
70 }
71
72 auto** p = static_cast<void**>(newBuf);
73 p[0] = head;
74
75 current = static_cast<void*>(&p[1]);
76 available = n;
77 nextSize = 2 * n;
78 head = newBuf;
79 }
80
81private:
82 void* current = nullptr;
83 size_t available = 0;
84 size_t nextSize = 1024;
85 void* head = nullptr;
86};
87
88#endif
monotonic_allocator(const monotonic_allocator &)=delete
monotonic_allocator()=default
monotonic_allocator(void *buffer, size_t bufferSize)
monotonic_allocator & operator=(monotonic_allocator &&)=delete
monotonic_allocator(size_t initialSize)
monotonic_allocator(monotonic_allocator &&)=delete
void * allocate(size_t bytes, size_t alignment)
monotonic_allocator & operator=(const monotonic_allocator &)=delete