Ocean
Loading...
Searching...
No Matches
base/Memory.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_BASE_MEMORY_H
9#define META_OCEAN_BASE_MEMORY_H
10
11#include "ocean/base/Base.h"
12#include "ocean/base/Worker.h"
13
14namespace Ocean
15{
16
17/**
18 * This class implements an object able to allocate memory.
19 * @ingroup base
20 */
21class Memory
22{
23 public:
24
25 /**
26 * Creates a new object without any allocated memory.
27 */
28 Memory() = default;
29
30 /**
31 * Move constructor.
32 * @param memory The memory object to be moved
33 */
34 inline Memory(Memory&& memory) noexcept;
35
36 /**
37 * Creates a new object and allocates a specified amount of memory.
38 * This function allows to allocated memory with a specific byte alignment, so that the start address of the memory is a multiple of the specified alignment.
39 * @param size The size of the memory to be allocated in bytes, with range [0, infinity)
40 * @param alignment The memory byte alignment of the allocated memory, in bytes, with range [1, infinity)
41 */
42 explicit inline Memory(const size_t size, const size_t alignment = size_t(1));
43
44 /**
45 * Creates a new object and uses externally allocated writable memory.
46 * This object will not be the owner of the memory, ensure that the external memory exists as long as this object exists.
47 * @param useData The external allocated memory which will be used, must be valid
48 * @param size The size of the external allocated memory, in bytes, with range [1, infinity)
49 */
50 inline Memory(void* useData, const size_t size);
51
52 /**
53 * Creates a new object and uses externally allocated read-only memory.
54 * This object will not be the owner of the memory, ensure that the external memory exists as long as this object exists.
55 * @param useData The external allocated memory which will be used, must be valid
56 * @param size The size of the external allocated memory, in bytes, with range [1, infinity)
57 */
58 inline Memory(const void* useData, const size_t size);
59
60 /**
61 * Releases the object and frees the memory if it holds any memory.
62 */
63 inline ~Memory();
64
65 /**
66 * Returns the pointer to the read-only memory which is allocated by this object.
67 * @return The memory allocated by this object, nullptr if no memory is allocated
68 */
69 [[nodiscard]] inline const void* constdata() const;
70
71 /**
72 * Returns the pointer to the writable memory which is allocated by this object.
73 * @return The memory allocated by this object, nullptr if no memory is allocated
74 */
75 [[nodiscard]] inline void* data();
76
77 /**
78 * Returns the pointer to the read-only memory which is allocated by this object.
79 * @param checkAlignment True, to apply an assert checking the byte alignment of the specified data type
80 * @return The memory allocated by this object, nullptr if no memory is allocated
81 * @tparam T The data type of the returning pointer
82 */
83 template <typename T>
84 [[nodiscard]] inline const T* constdata(const bool checkAlignment = true) const;
85
86 /**
87 * Returns the pointer to the writable memory which is allocated by this object.
88 * @param checkAlignment True, to apply an assert checking the byte alignment of the specified data type
89 * @return The memory allocated by this object, nullptr if no memory is allocated
90 * @tparam T The data type of the returning pointer
91 */
92 template <typename T>
93 [[nodiscard]] inline T* data(const bool checkAlignment = true);
94
95 /**
96 * Returns whether a specified memory range is entirely enclosed inside the memory managed by this object.
97 * @param start The (inclusive) pointer to the start of the memory range to be checked, must be valid
98 * @param size The size of the memory range to be checked, in bytes, with range [0, infinity)
99 * @return True, if so or if 'size == 0'
100 */
101 [[nodiscard]] inline bool isInside(const void* const start, const size_t size) const;
102
103 /**
104 * Returns whether a specified memory range is entirely enclosed inside the memory managed by this object.
105 * @param start The (inclusive) pointer to the start of the memory range to be checked, must be valid
106 * @param end The (exclusive) pointer to the first byte after the memory range to be checked, must be valid, with range [start, infinity)
107 * @return True, if so or if 'start == end'
108 */
109 [[nodiscard]] inline bool isInside(const void* const start, const void* const end) const;
110
111 /**
112 * Explicitly frees (releases) the memory before this object is released.
113 */
114 inline void free();
115
116 /**
117 * Returns the size of the memory in bytes.
118 * @return The memory's size in bytes, with range [0, infinity)
119 */
120 [[nodiscard]] inline size_t size() const;
121
122 /**
123 * Returns whether this object owns the memory.
124 * @return True, if the memory is owned; False, if the memory is owned externally
125 */
126 [[nodiscard]] inline bool isOwner() const;
127
128 /**
129 * Returns whether this object provides read-only memory only.
130 * @return True, if the memory is read-only; False, if the memory is writable
131 */
132 [[nodiscard]] inline bool isReadOnly() const;
133
134 /**
135 * Returns whether this object holds any memory.
136 * @return True, if so
137 */
138 [[nodiscard]] inline bool isNull() const;
139
140 /**
141 * Returns whether this object holds any memory.
142 * @return True, if so
143 */
144 [[nodiscard]] explicit inline operator bool() const;
145
146 /**
147 * Move operator.
148 * @param memory The memory object to be moved
149 */
150 inline Memory& operator=(Memory&& memory) noexcept;
151
152 /**
153 * Creates a new object and allocates enough memory necessary for 'elements' of type T.
154 * @param elements The number of elements of type T for which the new object will allocate memory, with range [0, infinity)
155 * @return The new memory object
156 * @tparam T The data type of the each element
157 */
158 template <typename T>
159 [[nodiscard]] static inline Memory create(const size_t elements);
160
161 /**
162 * Copies a block of memory using a worker object to speed up the process.
163 * @param target The target memory receiving the memory
164 * @param source The source memory block
165 * @param size Number of bytes to be copied
166 * @param worker Optional worker object
167 */
168 static inline void memcpy(void* target, const void* source, const unsigned int size, Worker* worker = nullptr);
169
170 /**
171 * Sets the value of a given memory block using a worker object to speed up the process.
172 * @param data Memory block to be set
173 * @param value The value to be set, only the first byte will be used as value
174 * @param size Number of bytes to be set
175 * @param worker Optional worker object
176 */
177 static inline void memset(void* data, const int value, const unsigned int size, Worker* worker = nullptr);
178
179 protected:
180
181 /**
182 * The disabled copy constructor.
183 * @param memory The memory object that would be copied
184 */
185 Memory(const Memory& memory) = delete;
186
187 /**
188 * The disabled assign operator.
189 * @param memory The memory object that would be assigned
190 */
191 Memory& operator=(const Memory& memory) = delete;
192
193 /**
194 * Copies a subset of the a memory block.
195 * @param target The target memory
196 * @param source The source memory
197 * @param firstByte First byte to be copied
198 * @param numberBytes Number of bytes to be copied
199 */
200 static inline void memcpySubset(uint8_t* target, const uint8_t* source, const unsigned int firstByte, const unsigned int numberBytes);
201
202 /**
203 * Sets a subset of a given memory block.
204 * @param data Memory block to be set
205 * @param value the value to be set
206 * @param firstByte First byte to be set
207 * @param numberBytes Number of bytes to be set
208 */
209 static inline void memsetSubset(uint8_t* data, const int value, const unsigned int firstByte, const unsigned int numberBytes);
210
211 protected:
212
213 /// The pointer to the memory which is allocated and owned by this object, this pointer is pointing to the memory which needs to be freed when disposing the memory object.
214 void* allocatedData_ = nullptr;
215
216 /// The pointer to the read-only aligned memory which is reported to be the actual memory pointer, this memory pointer must not be freed when disposing the memory object.
217 const void* constAlignedData_ = nullptr;
218
219 /// The pointer to the writable aligned memory which is reported to be the actual memory pointer, this memory pointer must not be freed when disposing the memory object.
220 void* alignedData_ = nullptr;
221
222 /// The size of the actual usable memory in bytes, with range [0, infinity)
223 size_t size_ = 0;
224};
225
226inline Memory::Memory(Memory&& memory) noexcept :
227 Memory()
228{
229 *this = std::move(memory);
230}
231
232inline Memory::Memory(const size_t size, const size_t alignment) :
233 Memory()
234{
235 ocean_assert(alignment >= size_t(1));
236
237 if (size != size_t(0))
238 {
239 static_assert(sizeof(uint8_t) == 1, "Invalid data type!");
240
241 allocatedData_ = malloc(size + alignment);
242 ocean_assert(allocatedData_ != nullptr);
243
244 if (allocatedData_ != nullptr)
245 {
246 const size_t alignmentOffset = (alignment - (size_t(allocatedData_) % alignment)) % alignment;
247
248 ocean_assert(alignmentOffset < alignment);
249 ocean_assert((size_t(allocatedData_) + alignmentOffset) % alignment == size_t(0));
250
251 alignedData_ = (void*)(((uint8_t*)allocatedData_) + alignmentOffset);
252 ocean_assert(alignedData_ >= allocatedData_);
253
254 constAlignedData_ = (const void*)(alignedData_);
255
256 size_ = size;
257 }
258
259 ocean_assert(isOwner());
260 ocean_assert(!isReadOnly());
261 }
262}
263
264inline Memory::Memory(void* useData, const size_t size) :
265 alignedData_(useData),
266 size_(size)
267{
268 ocean_assert(useData != nullptr);
269 ocean_assert(size > 0);
270
271 constAlignedData_ = (const void*)(alignedData_);
272
273 ocean_assert(allocatedData_ == nullptr);
274
275 ocean_assert(!isOwner());
276 ocean_assert(!isReadOnly());
277}
278
279inline Memory::Memory(const void* useData, const size_t size) :
280 constAlignedData_(useData),
281 size_(size)
282{
283 ocean_assert(useData != nullptr);
284 ocean_assert(size > 0);
285
286 ocean_assert(allocatedData_ == nullptr);
287 ocean_assert(alignedData_ == nullptr);
288
289 ocean_assert(!isOwner());
290 ocean_assert(isReadOnly());
291}
292
294{
295 free();
296}
297
298inline const void* Memory::constdata() const
299{
300 return constAlignedData_;
301}
302
303inline void* Memory::data()
304{
305 return alignedData_;
306}
307
308template<typename T>
309inline const T* Memory::constdata(const bool checkAlignment) const
310{
311 if (checkAlignment)
312 {
313 ocean_assert((size_t(constAlignedData_) % sizeof(T)) == 0);
314 }
315
316 return reinterpret_cast<const T*>(constAlignedData_);
317}
318
319template<typename T>
320inline T* Memory::data(const bool checkAlignment)
321{
322 if (checkAlignment)
323 {
324 ocean_assert((size_t(alignedData_) % sizeof(T)) == 0);
325 }
326
327 return reinterpret_cast<T*>(alignedData_);
328}
329
330inline bool Memory::isInside(const void* const start, const size_t size) const
331{
332 ocean_assert(start != nullptr);
333
334 if (size == 0)
335 {
336 return true;
337 }
338
339 if (constAlignedData_ == nullptr)
340 {
341 return false;
342 }
343
344 const uint8_t* const start_u8 = (const uint8_t*)(start);
345 const uint8_t* const constAlignedData_u8 = (const uint8_t*)(constAlignedData_);
346
347 return start_u8 >= constAlignedData_u8 && start_u8 + size <= constAlignedData_u8 + size_;
348}
349
350inline bool Memory::isInside(const void* const start, const void* const end) const
351{
352 ocean_assert(start != nullptr && end != nullptr);
353 ocean_assert(start <= end);
354
355 if (start == end)
356 {
357 return true;
358 }
359
360 if (constAlignedData_ == nullptr)
361 {
362 return false;
363 }
364
365 const void* const constAlignedDataEnd = (const void*)((const uint8_t*)(constAlignedData_) + size_);
366
367 return start >= constAlignedData_ && end <= constAlignedDataEnd && start < end;
368}
369
370inline void Memory::free()
371{
372 if (allocatedData_ != nullptr)
373 {
374 ocean_assert(alignedData_ != nullptr);
375
377
378 allocatedData_ = nullptr;
379 }
380
381 constAlignedData_ = nullptr;
382 alignedData_ = nullptr;
383 size_ = size_t(0);
384}
385
386inline size_t Memory::size() const
387{
388 return size_;
389}
390
391inline bool Memory::isOwner() const
392{
393 return allocatedData_ != nullptr;
394}
395
396inline bool Memory::isReadOnly() const
397{
398 return alignedData_ == nullptr;
399}
400
401inline bool Memory::isNull() const
402{
403 ocean_assert((constAlignedData_ == nullptr && size_ == size_t(0)) || (constAlignedData_ != nullptr && size_ != size_t(0)));
404
405 return constAlignedData_ == nullptr;
406}
407
408inline Memory::operator bool() const
409{
410 ocean_assert((constAlignedData_ == nullptr && size_ == size_t(0)) || (constAlignedData_ != nullptr && size_ != size_t(0)));
411
412 return constAlignedData_ != nullptr;
413}
414
415inline Memory& Memory::operator=(Memory&& memory) noexcept
416{
417 if (this != &memory)
418 {
419 free();
420
421 allocatedData_ = memory.allocatedData_;
422 constAlignedData_ = memory.constAlignedData_;
423 alignedData_ = memory.alignedData_;
424 size_ = memory.size_;
425
426 memory.allocatedData_ = nullptr;
427 memory.constAlignedData_ = nullptr;
428 memory.alignedData_ = nullptr;
429 memory.size_ = size_t(0);
430 }
431
432 return *this;
433}
434
435template <typename T>
436inline Memory Memory::create(const size_t elements)
437{
438 return Memory(sizeof(T) * elements, sizeof(T) /* we fore the data-type specific alignment */);
439}
440
441inline void Memory::memcpy(void* target, const void* source, const unsigned int size, Worker* worker)
442{
443 if (worker)
444 {
445 worker->executeFunction(Worker::Function::createStatic(&Memory::memcpySubset, (uint8_t*)target, (const uint8_t*)source, 0u, 0u), 0u, size, 2u, 3u, 1024u);
446 }
447 else
448 {
449 ::memcpy(target, source, size);
450 }
451}
452
453inline void Memory::memset(void* data, const int value, const unsigned int size, Worker* worker)
454{
455 if (worker)
456 {
457 worker->executeFunction(Worker::Function::createStatic(&Memory::memsetSubset, (uint8_t*)data, value, 0u, 0u), 0u, size, 2u, 3u, 1024u);
458 }
459 else
460 {
461 ::memset(data, value, size);
462 }
463}
464
465inline void Memory::memcpySubset(uint8_t* target, const uint8_t* source, const unsigned int firstByte, const unsigned int numberBytes)
466{
467 ocean_assert(target != nullptr);
468 ocean_assert(source != nullptr);
469
470 ::memcpy(target + firstByte, source + firstByte, numberBytes);
471}
472
473inline void Memory::memsetSubset(uint8_t* data, const int value, const unsigned int firstByte, const unsigned int numberBytes)
474{
475 ocean_assert(data != nullptr);
476
477 ::memset(data + firstByte, value, numberBytes);
478}
479
480}
481
482#endif // META_OCEAN_BASE_MEMORY_H
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition Caller.h:2876
This class implements an object able to allocate memory.
Definition base/Memory.h:22
bool isReadOnly() const
Returns whether this object provides read-only memory only.
Definition base/Memory.h:396
static Memory create(const size_t elements)
Creates a new object and allocates enough memory necessary for 'elements' of type T.
Definition base/Memory.h:436
bool isOwner() const
Returns whether this object owns the memory.
Definition base/Memory.h:391
Memory(const Memory &memory)=delete
The disabled copy constructor.
bool isInside(const void *const start, const size_t size) const
Returns whether a specified memory range is entirely enclosed inside the memory managed by this objec...
Definition base/Memory.h:330
size_t size() const
Returns the size of the memory in bytes.
Definition base/Memory.h:386
static void memcpySubset(uint8_t *target, const uint8_t *source, const unsigned int firstByte, const unsigned int numberBytes)
Copies a subset of the a memory block.
Definition base/Memory.h:465
void * allocatedData_
The pointer to the memory which is allocated and owned by this object, this pointer is pointing to th...
Definition base/Memory.h:214
bool isNull() const
Returns whether this object holds any memory.
Definition base/Memory.h:401
static void memset(void *data, const int value, const unsigned int size, Worker *worker=nullptr)
Sets the value of a given memory block using a worker object to speed up the process.
Definition base/Memory.h:453
size_t size_
The size of the actual usable memory in bytes, with range [0, infinity)
Definition base/Memory.h:223
const void * constAlignedData_
The pointer to the read-only aligned memory which is reported to be the actual memory pointer,...
Definition base/Memory.h:217
Memory & operator=(Memory &&memory) noexcept
Move operator.
Definition base/Memory.h:415
Memory()=default
Creates a new object without any allocated memory.
void * data()
Returns the pointer to the writable memory which is allocated by this object.
Definition base/Memory.h:303
static void memcpy(void *target, const void *source, const unsigned int size, Worker *worker=nullptr)
Copies a block of memory using a worker object to speed up the process.
Definition base/Memory.h:441
static void memsetSubset(uint8_t *data, const int value, const unsigned int firstByte, const unsigned int numberBytes)
Sets a subset of a given memory block.
Definition base/Memory.h:473
const void * constdata() const
Returns the pointer to the read-only memory which is allocated by this object.
Definition base/Memory.h:298
~Memory()
Releases the object and frees the memory if it holds any memory.
Definition base/Memory.h:293
void * alignedData_
The pointer to the writable aligned memory which is reported to be the actual memory pointer,...
Definition base/Memory.h:220
Memory & operator=(const Memory &memory)=delete
The disabled assign operator.
void free()
Explicitly frees (releases) the memory before this object is released.
Definition base/Memory.h:370
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
The namespace covering the entire Ocean framework.
Definition Accessor.h:15