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