heap.h 4.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2024 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not be
  19. // misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. #ifndef DFPSR_HEAP
  24. #define DFPSR_HEAP
  25. #include "SafePointer.h"
  26. namespace dsr {
  27. // TODO: Implement reference counting and connect a thread-safe handle type to replace std::shared_ptr.
  28. // This should build on top of a fixed size allocator that pre-computes which recycling bin to use.
  29. // Handles could be able to contain multiple elements with the same reference counter, which is useful for giving buffers value heads in images for faster access.
  30. // TODO: Return the allocation size in UnsafeAllocation, to avoid extra calls to heap_getAllocationSize?
  31. // TODO: Create a faster and simpler allocator for things that never live past a function call or frame.
  32. // Then you just free the whole thing when done with the allocations.
  33. // Good for small images and fixed size heads, but bad for lists being reallocated many times that should recycle memory instead.
  34. // A temporary allocator can then only allocate one thing at a time or free all allocations.
  35. // A fixed size can guarantee that there is no heap allocation done at runtime.
  36. // A dynamic size can have more memory added when needed.
  37. // In debug mode, each allocation will be properly destructed.
  38. // In release mode, everything is just left as it is.
  39. // The caller allocating memory decides if the memory should be cleared or not.
  40. // A thread local version would not need any locks, but should still align with cache lines for consistency with regular heap allocations.
  41. // TODO: Allow reserving heap allocations for a specific thread to prevent accidental sharing.
  42. // This can have a separate memory pool in thread local memory to avoid using a mutex.
  43. // The thread local storage can be used for small allocations, while larger allocations can be placed among the shared memory.
  44. // Allocate memory in the heap.
  45. // The size argument is the minimum number of bytes to allocate, but the result may give you more than you asked for.
  46. // Post-condition: Returns pointers to the payload and header.
  47. UnsafeAllocation heap_allocate(uint64_t minimumSize);
  48. // Pre-condition: The allocation pointer must point to the start of a payload allocated using heap_allocate, no offsets nor other allocators allowed.
  49. // Post-condition: Returns the number of available bytes in the allocation.
  50. // You may not read a single byte outside of it, because it might include padding that ends at uneven addresses.
  51. // To use more memory than requested, you must round it down to whole elements.
  52. // If the element's size is a power of two, you can pre-compute a bit mask using memory_createAlignmentAndMask for rounding down.
  53. uint64_t heap_getAllocationSize(uint8_t* allocation);
  54. // Only a pointer is needed, so that it can be sent as a function pointer to X11.
  55. // TODO: Use the allocation head's alignment as the minimum alignment by combining the masks in compile time.
  56. // Then it is possible to place the padded allocation header for heap memory at a fixed offset from the allocation start, so that the head can be accessed.
  57. // No extra offsets are allowed on the pointer used to free the memory.
  58. // TODO: Have a global variable containing the default memory pool.
  59. // When it is destructed, all allocations that are empty will be freed and a termination flag will be enabled so that any more allocations being freed after it will free the memory themselves.
  60. void heap_free(uint8_t *allocation);
  61. /*
  62. // TODO: Apply additional safety checks when freeing the allocation using SafePointer, making sure that the correct allocation is freed.
  63. template <typename T>
  64. void heap_free(SafePointer<T> allocation) {
  65. }
  66. */
  67. }
  68. #endif