openMSX
MemBuffer.hh
Go to the documentation of this file.
1#ifndef MEMBUFFER_HH
2#define MEMBUFFER_HH
3
4#include "MemoryOps.hh"
5#include <algorithm>
6#include <new> // for bad_alloc
7#include <cstddef>
8#include <cstdlib>
9#include <cassert>
10
11namespace openmsx {
12
28template<typename T, size_t ALIGNMENT = 0> class MemBuffer
29{
30public:
34 : dat(nullptr)
35#ifdef DEBUG
36 , sz(0)
37#endif
38 {
39 }
40
43 explicit MemBuffer(size_t size)
44 : dat(static_cast<T*>(my_malloc(size * sizeof(T))))
45#ifdef DEBUG
46 , sz(size)
47#endif
48 {
49 }
50
52 MemBuffer(MemBuffer&& other) noexcept
53 : dat(other.dat)
54#ifdef DEBUG
55 , sz(other.sz)
56#endif
57 {
58 other.dat = nullptr;
59 }
60
62 MemBuffer& operator=(MemBuffer&& other) noexcept
63 {
64 std::swap(dat, other.dat);
65#ifdef DEBUG
66 std::swap(sz , other.sz);
67#endif
68 return *this;
69 }
70
74 {
75 my_free(dat);
76 }
77
81 [[nodiscard]] const T* data() const { return dat; }
82 [[nodiscard]] T* data() { return dat; }
83
86 [[nodiscard]] const T& operator[](size_t i) const
87 {
88#ifdef DEBUG
89 assert(i < sz);
90#endif
91 return dat[i];
92 }
93 [[nodiscard]] T& operator[](size_t i)
94 {
95#ifdef DEBUG
96 assert(i < sz);
97#endif
98 return dat[i];
99 }
100
103 [[nodiscard]] bool empty() const { return !dat; }
104
111 void resize(size_t size)
112 {
113 if (size) {
114 dat = static_cast<T*>(my_realloc(dat, size * sizeof(T)));
115#ifdef DEBUG
116 sz = size;
117#endif
118 } else {
119 clear();
120 }
121 }
122
125 void clear()
126 {
127 my_free(dat);
128 dat = nullptr;
129#ifdef DEBUG
130 sz = 0;
131#endif
132 }
133
136 void swap(MemBuffer& other) noexcept
137 {
138 std::swap(dat, other.dat);
139#ifdef DEBUG
140 std::swap(sz , other.sz );
141#endif
142 }
143
144private:
145 // If the requested alignment is less or equally strict than the
146 // guaranteed alignment by the standard malloc()-like functions
147 // we use those. Otherwise we use platform specific functions to
148 // request aligned memory.
149 // A valid alternative would be to always use the platform specific
150 // functions. The only disadvantage is that we cannot use realloc()
151 // in that case (there are no, not even platform specific, functions
152 // to realloc memory with bigger than default alignment).
153 static constexpr bool SIMPLE_MALLOC = ALIGNMENT <= alignof(std::max_align_t);
154
155 [[nodiscard]] void* my_malloc(size_t bytes)
156 {
157 void* result;
158 if constexpr (SIMPLE_MALLOC) {
159 result = malloc(bytes);
160 if (!result && bytes) throw std::bad_alloc();
161 } else {
162 // already throws bad_alloc in case of error
163 result = MemoryOps::mallocAligned(ALIGNMENT, bytes);
164 }
165 return result;
166 }
167
168 void my_free(void* p)
169 {
170 if constexpr (SIMPLE_MALLOC) {
171 free(p);
172 } else {
174 }
175 }
176
177 [[nodiscard]] void* my_realloc(void* old, size_t bytes)
178 {
179 void* result;
180 if constexpr (SIMPLE_MALLOC) {
181 result = realloc(old, bytes);
182 if (!result && bytes) throw std::bad_alloc();
183 } else {
184 result = MemoryOps::mallocAligned(ALIGNMENT, bytes);
185 if (!result && bytes) throw std::bad_alloc();
187 }
188 return result;
189 }
190
191private:
192 T* dat;
193#ifdef DEBUG
194 size_t sz;
195#endif
196};
197
198} // namespace openmsx
199
200namespace std {
201 template<typename T>
203 {
204 l.swap(r);
205 }
206}
207
208#endif
This class manages the lifetime of a block of memory.
Definition: MemBuffer.hh:29
~MemBuffer()
Free the memory buffer.
Definition: MemBuffer.hh:73
MemBuffer()
Construct an empty MemBuffer, no memory is allocated.
Definition: MemBuffer.hh:33
void resize(size_t size)
Grow or shrink the memory block.
Definition: MemBuffer.hh:111
MemBuffer(size_t size)
Construct a (uninitialized) memory buffer of given size.
Definition: MemBuffer.hh:43
bool empty() const
No memory allocated?
Definition: MemBuffer.hh:103
MemBuffer(MemBuffer &&other) noexcept
Move constructor.
Definition: MemBuffer.hh:52
void swap(MemBuffer &other) noexcept
Swap the managed memory block of two MemBuffers.
Definition: MemBuffer.hh:136
MemBuffer & operator=(MemBuffer &&other) noexcept
Move assignment.
Definition: MemBuffer.hh:62
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:81
const T & operator[](size_t i) const
Access elements in the memory buffer.
Definition: MemBuffer.hh:86
T & operator[](size_t i)
Definition: MemBuffer.hh:93
void clear()
Free the allocated memory block and set the current size to 0.
Definition: MemBuffer.hh:125
void * mallocAligned(size_t alignment, size_t size)
Definition: MemoryOps.cc:254
void freeAligned(void *)
Definition: MemoryOps.cc:284
This file implemented 3 utility functions:
Definition: Autofire.cc:9
STL namespace.
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202
size_t size(std::string_view utf8)