Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
4.1KB

  1. #pragma once
  2. #include <cstdlib>
  3. #include <utility>
  4. //! Allocator Base class
  5. //! subclasses must specify allocation and deallocation
  6. class Allocator
  7. {
  8. public:
  9. Allocator(void);
  10. Allocator(const Allocator&) = delete;
  11. virtual ~Allocator(void);
  12. virtual void *alloc_mem(size_t mem_size) = 0;
  13. virtual void dealloc_mem(void *memory) = 0;
  14. template <typename T, typename... Ts>
  15. T *alloc(Ts&&... ts)
  16. {
  17. void *data = alloc_mem(sizeof(T));
  18. if(!data)
  19. return nullptr;
  20. return new (data) T(std::forward<Ts>(ts)...);
  21. }
  22. template <typename T, typename... Ts>
  23. T *valloc(size_t len, Ts&&... ts)
  24. {
  25. T *data = (T*)alloc_mem(len*sizeof(T));
  26. if(!data)
  27. return nullptr;
  28. for(unsigned i=0; i<len; ++i)
  29. new ((void*)&data[i]) T(std::forward<Ts>(ts)...);
  30. return data;
  31. }
  32. template <typename T>
  33. void dealloc(T*&t)
  34. {
  35. if(t) {
  36. t->~T();
  37. dealloc_mem((void*)t);
  38. t = nullptr;
  39. }
  40. }
  41. //Destructor Free Version
  42. template <typename T>
  43. void devalloc(T*&t)
  44. {
  45. if(t) {
  46. dealloc_mem(t);
  47. t = nullptr;
  48. }
  49. }
  50. template <typename T>
  51. void devalloc(size_t elms, T*&t)
  52. {
  53. if(t) {
  54. for(size_t i=0; i<elms; ++i)
  55. (t+i)->~T();
  56. dealloc_mem(t);
  57. t = nullptr;
  58. }
  59. }
  60. virtual void addMemory(void *, size_t mem_size) = 0;
  61. //Return true if the current pool cannot allocate n chunks of chunk_size
  62. virtual bool lowMemory(unsigned n, size_t chunk_size) const = 0;
  63. bool memFree(void *pool) const;
  64. //returns number of pools
  65. int memPools() const;
  66. int freePools() const;
  67. unsigned long long totalAlloced() const;
  68. struct AllocatorImpl *impl;
  69. };
  70. //! the allocator for normal use
  71. class AllocatorClass : public Allocator
  72. {
  73. public:
  74. void *alloc_mem(size_t mem_size);
  75. void dealloc_mem(void *memory);
  76. void addMemory(void *, size_t mem_size);
  77. bool lowMemory(unsigned n, size_t chunk_size) const;
  78. using Allocator::Allocator;
  79. };
  80. typedef AllocatorClass Alloc;
  81. //! the dummy allocator, which does not allow any allocation
  82. class DummyAllocator : public Allocator
  83. {
  84. void not_allowed() const {
  85. throw "(de)allocation forbidden"; // TODO: std exception
  86. }
  87. public:
  88. void *alloc_mem(size_t ) { return not_allowed(), nullptr; }
  89. void dealloc_mem(void* ) { not_allowed(); } // TODO: more functions?
  90. void addMemory(void *, size_t ) { not_allowed(); }
  91. bool lowMemory(unsigned , size_t ) const { return not_allowed(), true; }
  92. using Allocator::Allocator;
  93. };
  94. extern DummyAllocator DummyAlloc;
  95. /**
  96. * General notes on Memory Allocation Within ZynAddSubFX
  97. * -----------------------------------------------------
  98. *
  99. * - Parameter Objects Are never allocated within the realtime thread
  100. * - Effects, notes and note subcomponents must be allocated with an allocator
  101. * - 5M Chunks are used to give the allocator the memory it wants
  102. * - If there are 3 chunks that are unused then 1 will be deallocated
  103. * - The system will request more allocated space if 5x 1MB chunks cannot be
  104. * allocated at any given time (this is likely huge overkill, but if this is
  105. * satisfied, then a lot of note spamming would be needed to run out of
  106. * space)
  107. *
  108. * - Things will get a bit weird around the effects due to how pointer swaps
  109. * occur
  110. * * When a new Part instance is provided it may or may not come with some
  111. * instrument effects
  112. * * Merging blocks is an option, but one that is not going to likely be
  113. * implmented too soon, thus all effects need to be reallocated when the
  114. * pointer swap occurs
  115. * * The old effect is extracted from the manager
  116. * * A new one is constructed with a deep copy
  117. * * The old one is returned to middleware for deallocation
  118. */