/* * Copyright (C) 2020 Linux Studio Plugins Project * (C) 2020 Vladimir Sadovnikov * * This file is part of lsp-plugins * Created on: 14 янв. 2019 г. * * lsp-plugins 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-plugins 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-plugins. If not, see . */ #include #include #include #include namespace lsp { BasicAllocator3D::BasicAllocator3D(size_t sz_of, size_t c_size) { nChunks = 0; nShift = int_log2(c_size); nMask = (1 << nShift) - 1; nSizeOf = sz_of; nAllocated = 0; vChunks = NULL; pCurr = NULL; nLeft = 0; } BasicAllocator3D::~BasicAllocator3D() { do_destroy(); } uint8_t *BasicAllocator3D::get_chunk(size_t id) { // Reallocate chunk index if too small if (id >= nChunks) { size_t cap = (id + 0x10) & (~0x0f); uint8_t **nc = reinterpret_cast(::realloc(vChunks, sizeof(uint8_t *) * cap)); if (nc == NULL) return NULL; // Initialize pointers for (size_t i=nChunks; i(::malloc(nSizeOf << nShift)); if (chunk == NULL) return NULL; vChunks[id] = chunk; return chunk; } void *BasicAllocator3D::do_get(size_t idx) { if (idx >= nAllocated) return NULL; uint8_t *chunk = vChunks[idx >> nShift]; return &chunk[nSizeOf * (idx & nMask)]; } void *BasicAllocator3D::do_alloc() { // Try to allocate from current chunk if (nLeft <= 0) { pCurr = get_chunk(nAllocated >> nShift); if (pCurr == NULL) return NULL; nLeft = nMask; // (1 << nShift) - 1 } else --nLeft; uint8_t *p = pCurr; pCurr += nSizeOf; ++nAllocated; return p; } size_t BasicAllocator3D::do_alloc_n(void **ptr, size_t n) { size_t left = n; while (left > 0) { // Try to allocate from current chunk if (nLeft <= 0) { pCurr = get_chunk(nAllocated >> nShift); if (pCurr == NULL) break; nLeft = (1 << nShift); } // Allocate N items size_t to_alloc = (nLeft > n) ? n : nLeft; nLeft -= to_alloc; nAllocated += to_alloc; uint8_t *p = pCurr; while (to_alloc--) { *(ptr++) = p; p += nSizeOf; } pCurr = p; } return n - left; } ssize_t BasicAllocator3D::do_ialloc(void **p) { // Try to allocate from current chunk if (nLeft <= 0) { pCurr = get_chunk(nAllocated >> nShift); if (pCurr == NULL) return -STATUS_NO_MEM; nLeft = nMask; // (1 << nShift) - 1 } else --nLeft; *p = pCurr; pCurr += nSizeOf; return nAllocated++; } void BasicAllocator3D::do_destroy() { if (vChunks != NULL) { for (size_t i=0; inChunks); swap(nShift, src->nShift); swap(nMask, src->nMask); swap(nSizeOf, src->nSizeOf); swap(nAllocated, src->nAllocated); swap(vChunks, src->vChunks); swap(pCurr, src->pCurr); swap(nLeft, src->nLeft); } bool BasicAllocator3D::do_validate(const void *ptr) const { if (ptr == NULL) return true; const uint8_t *uptr = reinterpret_cast(ptr); ssize_t csize = nSizeOf << nShift; for (size_t i=0; i= csize)) continue; if ((delta % nSizeOf) != 0) return false; delta /= nSizeOf; return ((i << nShift) + delta) < nAllocated; } return false; } ssize_t BasicAllocator3D::calc_index_of(const void *ptr) const { if (ptr == NULL) return -1; const uint8_t *uptr = reinterpret_cast(ptr); ssize_t csize = nSizeOf << nShift; ssize_t offset = 0; ssize_t chunk_cap = 1 << nShift; for (size_t i=0; i= csize)) continue; if ((delta % nSizeOf) != 0) return -1; return offset + delta / nSizeOf; } return -1; } }