Grok  9.5.0
MemManager.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2021 Grok Image Compression Inc.
3  *
4  * This source code is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Affero General Public License, version 3,
6  * as published by the Free Software Foundation.
7  *
8  * This source code is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU Affero General Public License for more details.
12  *
13  * You should have received a copy of the GNU Affero General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  *
17  * This source code incorporates work covered by the BSD 2-clause license.
18  * Please see the LICENSE file in the root directory for details.
19  *
20  */
21 #pragma once
22 
23 #if defined(__GNUC__) && !defined(GROK_SKIP_POISON)
24 #pragma GCC poison malloc calloc realloc free
25 #endif
26 
27 #include <cstddef>
28 
29 namespace grk
30 {
31 uint32_t grkMakeAlignedWidth(uint32_t width);
37 void* grkMalloc(size_t size);
44 void* grkCalloc(size_t numOfElements, size_t sizeOfElements);
50 void* grkAlignedMalloc(size_t size);
51 void grkAlignedFree(void* ptr);
58 void* grkRealloc(void* m, size_t s);
63 void grkFree(void* m);
64 
65 template<typename T>
67 {
68  T* alloc(size_t length)
69  {
70  return new T[length];
71  }
72  void dealloc(T* buf)
73  {
74  delete[] buf;
75  }
76 };
77 template<typename T>
79 {
80  T* alloc(size_t length)
81  {
82  return (T*)grkAlignedMalloc(length * sizeof(T));
83  }
84  void dealloc(T* buf)
85  {
86  grkAlignedFree(buf);
87  }
88 };
89 template<typename T, template<typename TT> typename A>
90 struct grkBuffer : A<T>
91 {
92  grkBuffer(T* buffer, size_t off, size_t length, bool ownsData)
93  : buf(buffer), offset(off), len(length), owns_data(ownsData)
94  {}
95  grkBuffer(T* buffer, size_t length) : grkBuffer(buffer, 0, length, false) {}
96  grkBuffer() : grkBuffer(0, 0, 0, false) {}
97  grkBuffer(T* buffer, size_t length, bool ownsData) : grkBuffer(buffer, 0, length, ownsData) {}
98  virtual ~grkBuffer()
99  {
100  dealloc();
101  }
102  explicit grkBuffer(const grkBuffer& rhs)
103  {
104  this->operator=(rhs);
105  }
106  grkBuffer& operator=(const grkBuffer& rhs) // copy assignment
107  {
108  return operator=(&rhs);
109  }
110  grkBuffer& operator=(const grkBuffer* rhs) // copy assignment
111  {
112  if(this != rhs)
113  { // self-assignment check expected
114  buf = rhs->buf;
115  offset = rhs->offset;
116  len = rhs->len;
117  owns_data = false;
118  }
119  return *this;
120  }
121  virtual bool alloc(size_t length)
122  {
123  if(buf && len > length)
124  return true;
125  dealloc();
126  buf = A<T>::alloc(length);
127  if(!buf)
128  return false;
129  len = length;
130  offset = 0;
131  owns_data = true;
132 
133  return true;
134  }
135  virtual void dealloc()
136  {
137  if(owns_data)
138  A<T>::dealloc(buf);
139  buf = nullptr;
140  owns_data = false;
141  offset = 0;
142  len = 0;
143  }
144  // set buf to buf without owning it
145  void attach(T* buffer)
146  {
148  buf = buffer;
149  }
150  // set buf to buf and own it
151  void acquire(T* buffer)
152  {
154  buffer = buf;
155  owns_data = true;
156  }
157  // transfer buf to buf, and cease owning it
158  void transfer(T** buffer)
159  {
160  if(buffer)
161  {
162  *buffer = buf;
163  buf = nullptr;
164  owns_data = false;
165  }
166  }
167  size_t remainingLength(void)
168  {
169  return len - offset;
170  }
171  void incrementOffset(ptrdiff_t off)
172  {
173  /* we allow the offset to move to one location beyond end of buffer segment*/
174  if(off > 0)
175  {
176  if(offset > (size_t)(SIZE_MAX - (size_t)off))
177  {
178  GRK_WARN("grkBufferU8: overflow");
179  offset = len;
180  }
181  else if(offset + (size_t)off > len)
182  {
183 #ifdef DEBUG_SEG_BUF
184  GRK_WARN("grkBufferU8: attempt to increment buffer offset out of bounds");
185 #endif
186  offset = len;
187  }
188  else
189  {
190  offset = offset + (size_t)off;
191  }
192  }
193  else if(off < 0)
194  {
195  if(offset < (size_t)(-off))
196  {
197  GRK_WARN("grkBufferU8: underflow");
198  offset = 0;
199  }
200  else
201  {
202  offset = (size_t)((ptrdiff_t)offset + off);
203  }
204  }
205  }
206  T* currPtr(void) const
207  {
208  if(!buf)
209  return nullptr;
210  return buf + offset;
211  }
212  T* buf; /* internal array*/
213  size_t offset; /* current offset into array */
214  size_t len; /* length of array */
215  bool owns_data; /* true if buffer manages the buf array */
216 };
217 
220 
221 template<typename T, template<typename TT> typename A>
222 struct grkBuffer2d : private grkBuffer<T, A>, public grkRectU32
223 {
224  grkBuffer2d(T* buffer, bool ownsData, uint32_t w, uint32_t strd, uint32_t h)
225  : grkBuffer<T, A>(buffer, ownsData), grkRectU32(0, 0, w, h), stride(strd)
226  {}
227  grkBuffer2d(uint32_t w, uint32_t strd, uint32_t h) : grkBuffer2d(nullptr, false, w, strd, h) {}
228  grkBuffer2d(uint32_t w, uint32_t h) : grkBuffer2d(w, 0, h) {}
229  explicit grkBuffer2d(const grkRectU32* b)
230  : grkBuffer<T, A>(nullptr, false), grkRectU32(b->x0, b->y0, b->x1, b->y1), stride(0)
231  {}
232  grkBuffer2d(void) : grkBuffer2d(nullptr, 0, 0, 0, false) {}
233  explicit grkBuffer2d(const grkBuffer2d& rhs)
234  : grkBuffer<T, A>(rhs), grkRectU32(rhs), stride(rhs.stride)
235  {}
236  grkBuffer2d& operator=(const grkBuffer2d& rhs) // copy assignment
237  {
238  return operator=(&rhs);
239  }
240  grkBuffer2d& operator=(const grkBuffer2d* rhs) // copy assignment
241  {
242  if(this != rhs)
243  { // self-assignment check expected
246  stride = rhs->stride;
247  }
248  return *this;
249  }
250  virtual ~grkBuffer2d() = default;
251  bool alloc2d(bool clear)
252  {
253  if(!this->buf && width() && height())
254  {
255  if(!stride)
257  uint64_t data_size_needed = (uint64_t)stride * height() * sizeof(T);
258  if(!data_size_needed)
259  return true;
260  if(!grkBuffer<T, A>::alloc(data_size_needed))
261  {
262  grk::GRK_ERROR("Failed to allocate aligned memory buffer of dimensions %u x %u",
263  stride, height());
264  return false;
265  }
266  if(clear)
267  memset(this->buf, 0, data_size_needed);
268  }
269 
270  return true;
271  }
272  // set buf to buf without owning it
273  void attach(T* buffer, uint32_t strd)
274  {
275  grkBuffer<T, A>::attach(buffer);
276  stride = strd;
277  }
278  // set buf to buf and own it
279  void acquire(T* buffer, uint32_t strd)
280  {
281  grkBuffer<T, A>::acquire(buffer);
282  stride = strd;
283  }
284  // transfer buf to buf, and cease owning it
285  void transfer(T** buffer, uint32_t* strd)
286  {
287  if(buffer)
288  {
290  *strd = stride;
291  }
292  }
293 
300  {
301  return !(win.x0 >= x1 || win.x1 <= x0 || win.x1 > x1 || win.y0 >= y1 || win.y1 <= win.y0 ||
302  win.y1 > y1);
303  }
304 
315  bool read(grkRectU32 window, int32_t* dest, const uint32_t destColStride,
316  const uint32_t destStride)
317  {
318  if(!isWindowValid(window))
319  return false;
320 
321  // 1. calculate overlap
322 
323  return true;
324  }
325 
335  bool write(grkRectU32 window, const int32_t* src, const uint32_t srcColStride,
336  const uint32_t srcStride)
337  {
338  if(!isWindowValid(window))
339  return false;
340 
341  return true;
342  }
343 
344  bool copy_data(T* dest, uint32_t dest_w, uint32_t dest_h, uint32_t dest_stride) const
345  {
346  assert(dest_w <= width());
347  assert(dest_h <= height());
348  assert(dest_stride <= stride);
349  if(dest_w > width() || dest_h > height() || dest_stride > stride)
350  return false;
351  if(!this->buf)
352  return false;
353  auto src_ptr = this->buf;
354  auto dest_ptr = dest;
355  for(uint32_t j = 0; j < dest_h; ++j)
356  {
357  memcpy(dest_ptr, src_ptr, dest_w * sizeof(T));
358  dest_ptr += dest_stride;
359  src_ptr += stride;
360  }
361  return true;
362  }
363  // rhs coordinates are in "this" coordinate system
364  template<typename F>
365  void copy(const grkBuffer2d& rhs, F filter)
366  {
367  auto inter = this->intersection(rhs);
368  if(!inter.non_empty())
369  return;
370 
371  T* dest = this->buf + (inter.y0 * stride + inter.x0);
372  T* src = rhs.buf + ((inter.y0 - rhs.y0) * rhs.stride + inter.x0 - rhs.x0);
373  uint32_t len = inter.width();
374  for(uint32_t j = inter.y0; j < inter.y1; ++j)
375  {
376  filter.copy(dest, src, len);
377  dest += stride;
378  src += rhs.stride;
379  }
380  }
381  T* getBuffer(void) const
382  {
383  return this->currPtr();
384  }
385  uint32_t stride;
386 };
387 
388 } // namespace grk
#define SIZE_MAX
Definition: MemManager.cpp:30
Copyright (C) 2016-2021 Grok Image Compression Inc.
Definition: ICacheable.h:20
void grkAlignedFree(void *ptr)
Definition: MemManager.cpp:125
void grkFree(void *ptr)
Deallocates or frees a memory block.
Definition: MemManager.cpp:145
void GRK_ERROR(const char *fmt,...)
Definition: logger.cpp:58
void GRK_WARN(const char *fmt,...)
Definition: logger.cpp:49
void * grkAlignedMalloc(size_t size)
Allocate memory aligned to a 16 byte boundary.
Definition: MemManager.cpp:121
void * grkMalloc(size_t size)
Allocate an uninitialized memory block.
Definition: MemManager.cpp:106
void * grkCalloc(size_t num, size_t size)
Allocate a memory block with elements initialized to 0.
Definition: MemManager.cpp:113
void * grkRealloc(void *ptr, size_t new_size)
Reallocate memory blocks.
Definition: MemManager.cpp:138
uint32_t grkMakeAlignedWidth(uint32_t width)
Definition: MemManager.cpp:38
Definition: MemManager.h:79
void dealloc(T *buf)
Definition: MemManager.h:84
T * alloc(size_t length)
Definition: MemManager.h:80
Definition: MemManager.h:67
T * alloc(size_t length)
Definition: MemManager.h:68
void dealloc(T *buf)
Definition: MemManager.h:72
Definition: MemManager.h:223
bool copy_data(T *dest, uint32_t dest_w, uint32_t dest_h, uint32_t dest_stride) const
Definition: MemManager.h:344
grkBuffer2d(T *buffer, bool ownsData, uint32_t w, uint32_t strd, uint32_t h)
Definition: MemManager.h:224
grkBuffer2d(void)
Definition: MemManager.h:232
bool read(grkRectU32 window, int32_t *dest, const uint32_t destColStride, const uint32_t destStride)
Read the contents of a rectangular window into a user buffer.
Definition: MemManager.h:315
grkBuffer2d(const grkBuffer2d &rhs)
Definition: MemManager.h:233
void attach(T *buffer, uint32_t strd)
Definition: MemManager.h:273
bool write(grkRectU32 window, const int32_t *src, const uint32_t srcColStride, const uint32_t srcStride)
Write the contents of a rectangular window from a user buffer.
Definition: MemManager.h:335
grkBuffer2d & operator=(const grkBuffer2d &rhs)
Definition: MemManager.h:236
grkBuffer2d(const grkRectU32 *b)
Definition: MemManager.h:229
virtual ~grkBuffer2d()=default
bool isWindowValid(grkRectU32 win)
Returns whether window bounds are valid (non empty and within buffer bounds)
Definition: MemManager.h:299
grkBuffer2d & operator=(const grkBuffer2d *rhs)
Definition: MemManager.h:240
uint32_t stride
Definition: MemManager.h:385
grkBuffer2d(uint32_t w, uint32_t h)
Definition: MemManager.h:228
void acquire(T *buffer, uint32_t strd)
Definition: MemManager.h:279
void copy(const grkBuffer2d &rhs, F filter)
Definition: MemManager.h:365
T * getBuffer(void) const
Definition: MemManager.h:381
grkBuffer2d(uint32_t w, uint32_t strd, uint32_t h)
Definition: MemManager.h:227
bool alloc2d(bool clear)
Definition: MemManager.h:251
void transfer(T **buffer, uint32_t *strd)
Definition: MemManager.h:285
Definition: MemManager.h:91
void acquire(T *buffer)
Definition: MemManager.h:151
grkBuffer()
Definition: MemManager.h:96
grkBuffer(T *buffer, size_t length, bool ownsData)
Definition: MemManager.h:97
void incrementOffset(ptrdiff_t off)
Definition: MemManager.h:171
T * currPtr(void) const
Definition: MemManager.h:206
grkBuffer & operator=(const grkBuffer *rhs)
Definition: MemManager.h:110
void transfer(T **buffer)
Definition: MemManager.h:158
virtual ~grkBuffer()
Definition: MemManager.h:98
grkBuffer & operator=(const grkBuffer &rhs)
Definition: MemManager.h:106
bool owns_data
Definition: MemManager.h:215
size_t offset
Definition: MemManager.h:213
grkBuffer(T *buffer, size_t off, size_t length, bool ownsData)
Definition: MemManager.h:92
grkBuffer(const grkBuffer &rhs)
Definition: MemManager.h:102
virtual void dealloc()
Definition: MemManager.h:135
T * buf
Definition: MemManager.h:212
virtual bool alloc(size_t length)
Definition: MemManager.h:121
grkBuffer(T *buffer, size_t length)
Definition: MemManager.h:95
size_t remainingLength(void)
Definition: MemManager.h:167
void attach(T *buffer)
Definition: MemManager.h:145
size_t len
Definition: MemManager.h:214
uint32_t x1
Definition: util.h:96
uint32_t y0
Definition: util.h:96
grkRect< uint32_t > & operator=(const grkRect< uint32_t > &rhs)
Definition: util.h:129
uint32_t width() const
Definition: util.h:209
grkRect< uint32_t > intersection(const grkRect< uint32_t > rhs) const
Definition: util.h:173
uint32_t height() const
Definition: util.h:213
uint32_t y1
Definition: util.h:96
uint32_t x0
Definition: util.h:96