1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 14 янв. 2019 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef INCLUDE_CORE_3D_ALLOCATOR3D_H_ 23 #define INCLUDE_CORE_3D_ALLOCATOR3D_H_ 24 25 #include <core/types.h> 26 27 namespace lsp 28 { 29 /** 30 * Fixed-pointer allocator, allocates data grouped into partitions or 'chunks' 31 * to avoid huge memory fragmentation 32 */ 33 class BasicAllocator3D 34 { 35 protected: 36 size_t nChunks; // Number of chunks in vChunks array 37 size_t nShift; // Chunk identifier shift 38 size_t nMask; // Chunk item mask 39 size_t nSizeOf; // Size of record (in bytes) 40 size_t nAllocated; // Number of allocated items 41 uint8_t **vChunks; // List of all chunks 42 uint8_t *pCurr; // Current chunk 43 size_t nLeft; // Number of left items 44 45 protected: 46 uint8_t *get_chunk(size_t id); 47 void *do_alloc(); 48 void do_clear(); 49 ssize_t do_ialloc(void **p); 50 void *do_get(size_t idx); 51 void do_destroy(); 52 size_t do_alloc_n(void **ptr, size_t n); 53 void do_swap(BasicAllocator3D *alloc); 54 bool do_validate(const void *ptr) const; 55 ssize_t calc_index_of(const void *ptr) const; 56 57 public: 58 explicit BasicAllocator3D(size_t sz_of, size_t c_size); 59 ~BasicAllocator3D(); 60 }; 61 62 template <class T> 63 class Allocator3D: public BasicAllocator3D 64 { 65 public: 66 /** 67 * Constructor 68 * @param csize chunk size, will be rounded to be power of 2 69 */ Allocator3D(size_t csize)70 explicit Allocator3D(size_t csize): BasicAllocator3D(sizeof(T), csize) {} 71 72 public: 73 /** 74 * Allocate single item 75 * @return pointer to allocated single item or NULL 76 */ alloc()77 inline T *alloc() { return reinterpret_cast<T *>(do_alloc()); } 78 79 /** 80 * Allocate single item 81 * @return pointer to allocated single item or negative error status 82 */ ialloc(T ** dst)83 inline ssize_t ialloc(T **dst) { return do_ialloc(reinterpret_cast<void **>(dst)); } 84 85 /** 86 * Allocate single item and initialize with value 87 * @param src value to initialize 88 * @return pointer to allocated item or NULL 89 */ alloc(const T * src)90 inline T *alloc(const T *src) 91 { 92 T *res = reinterpret_cast<T *>(do_alloc()); 93 if (res != NULL) 94 *res = *src; 95 return res; 96 } 97 98 /** 99 * Allocate single item 100 * @return pointer to allocated single item or NULL 101 */ ialloc(T ** dst,const T * src)102 inline ssize_t ialloc(T **dst, const T *src) { 103 size_t res = do_ialloc(reinterpret_cast<void **>(dst)); 104 if (*dst != NULL) 105 **dst = *src; 106 return res; 107 } 108 109 /** 110 * Allocate single item and initialize with value 111 * @param src value to initialize 112 * @return pointer to allocated item or NULL 113 */ alloc(const T & src)114 inline T *alloc(const T &src) 115 { 116 T *res = reinterpret_cast<T *>(do_alloc()); 117 if (res != NULL) 118 *res = src; 119 return res; 120 } 121 122 /** 123 * Allocate single item 124 * @return pointer to allocated single item or NULL 125 */ ialloc(T ** dst,const T & src)126 inline ssize_t ialloc(T **dst, const T &src) { 127 size_t res = do_ialloc(reinterpret_cast<void **>(dst)); 128 if (*dst != NULL) 129 **dst = src; 130 return res; 131 } 132 133 /** 134 * Allocate set of items 135 * @param retval pointer to store pointers to allocated elements 136 * @param n number of elements to allocate 137 * @return actual number of allocated items 138 */ alloc_n(T ** retval,size_t n)139 inline size_t alloc_n(T **retval, size_t n) { return do_alloc_n(reinterpret_cast<void **>(retval), n); } 140 141 /** 142 * Get number of allocated items 143 * @return number of allocated items 144 */ size()145 inline size_t size() const { return nAllocated; } 146 147 /** 148 * Get number of elements per one chunk 149 * @return number of elements per one chunk 150 */ chunk_size()151 inline size_t chunk_size() const { return 1 << nShift; } 152 153 /** 154 * Get number of allocated chunks 155 * @return number of allocated chunks 156 */ chunks()157 inline size_t chunks() const { return nChunks; } 158 159 /** 160 * Get chunk pointer 161 * @param id chunk identifier 162 * @return chunk pointer 163 */ chunk(size_t id)164 inline T *chunk(size_t id) { return (id < nChunks) ? reinterpret_cast<T *>(vChunks[id]) : NULL; } 165 166 /** 167 * Get element at specified index 168 * @param idx element at specified index 169 * @return element at specified index or NULL if index is invalid 170 */ get(size_t idx)171 inline T *get(size_t idx) { return reinterpret_cast<T *>(do_get(idx)); } 172 173 /** 174 * Get element at specified index 175 * @param idx element at specified index 176 * @return element at specified index or NULL if index is invalid 177 */ 178 inline T * operator[] (size_t idx) { return do_get(idx); } 179 180 /** 181 * Swap internal contents with another allocator 182 * @param src allocator to perform swapping 183 */ swap(Allocator3D<T> * src)184 inline void swap(Allocator3D<T> *src) { do_swap(src); }; 185 186 /** Drop all allocated data 187 * 188 */ destroy()189 inline void destroy() { do_destroy(); }; 190 191 /** Drop all allocated data (similar to destroy) 192 * 193 */ flush()194 inline void flush() { do_destroy(); }; 195 196 /** Drop all allocated data (currently similar to destroy) 197 * 198 */ clear()199 inline void clear() { do_clear(); }; 200 201 /** 202 * Ensure that the specified pointer is right pointer, NULL pointers 203 * also return positive result 204 * @param ptr pointer 205 * @return true if pointer is right and belongs to this allocator 206 */ validate(const void * ptr)207 inline bool validate(const void *ptr) const { return do_validate(ptr); }; 208 209 /** 210 * Get index of the item in allocator 211 * @param ptr pointer to the item 212 * @return index of the item or negative value on error 213 */ index_of(const void * ptr)214 inline ssize_t index_of(const void *ptr) const { return calc_index_of(ptr); } 215 }; 216 } 217 218 #endif /* INCLUDE_CORE_3D_ALLOCATOR3D_H_ */ 219