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 
11 namespace openmsx {
12 
28 template<typename T, size_t ALIGNMENT = 0> class MemBuffer
29 {
30 public:
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 
144 private:
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 (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 (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 (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 
191 private:
192  T* dat;
193 #ifdef DEBUG
194  size_t sz;
195 #endif
196 };
197 
198 } // namespace openmsx
199 
200 namespace std {
201  template<typename T>
203  {
204  l.swap(r);
205  }
206 }
207 
208 #endif
openmsx::MemBuffer::clear
void clear()
Free the allocated memory block and set the current size to 0.
Definition: MemBuffer.hh:125
openmsx::MemBuffer::data
T * data()
Definition: MemBuffer.hh:82
openmsx::MemBuffer::swap
void swap(MemBuffer &other) noexcept
Swap the managed memory block of two MemBuffers.
Definition: MemBuffer.hh:136
MemoryOps.hh
openmsx::MemoryOps::freeAligned
void freeAligned(void *)
Definition: MemoryOps.cc:281
openmsx::MemBuffer::empty
bool empty() const
No memory allocated?
Definition: MemBuffer.hh:103
openmsx::MemBuffer::operator=
MemBuffer & operator=(MemBuffer &&other) noexcept
Move assignment.
Definition: MemBuffer.hh:62
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:227
openmsx::MemBuffer::MemBuffer
MemBuffer(size_t size)
Construct a (uninitialized) memory buffer of given size.
Definition: MemBuffer.hh:43
openmsx::MemBuffer::resize
void resize(size_t size)
Grow or shrink the memory block.
Definition: MemBuffer.hh:111
openmsx::MemBuffer
This class manages the lifetime of a block of memory.
Definition: MemBuffer.hh:29
openmsx::MemBuffer::operator[]
T & operator[](size_t i)
Definition: MemBuffer.hh:93
openmsx::MemoryOps::mallocAligned
void * mallocAligned(size_t alignment, size_t size)
Definition: MemoryOps.cc:251
openmsx::MemBuffer::MemBuffer
MemBuffer(MemBuffer &&other) noexcept
Move constructor.
Definition: MemBuffer.hh:52
std::swap
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202
openmsx::MemBuffer::data
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:81
openmsx::MemBuffer::~MemBuffer
~MemBuffer()
Free the memory buffer.
Definition: MemBuffer.hh:73
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
openmsx::MemBuffer::MemBuffer
MemBuffer()
Construct an empty MemBuffer, no memory is allocated.
Definition: MemBuffer.hh:33
openmsx::MemBuffer::operator[]
const T & operator[](size_t i) const
Access elements in the memory buffer.
Definition: MemBuffer.hh:86