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
|
/*
* Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
*
* This file is part of lsp-common-lib
* Created on: 3 апр. 2020 г.
*
* lsp-common-lib 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-common-lib 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-common-lib. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef LSP_PLUG_IN_COMMON_ALLOC_H_
#define LSP_PLUG_IN_COMMON_ALLOC_H_
#include <lsp-plug.in/common/version.h>
#include <lsp-plug.in/common/types.h>
#include <lsp-plug.in/stdlib/stdlib.h>
namespace lsp
{
inline size_t align_size(size_t size, size_t align)
{
size_t off = size % align;
return (off) ? (size + align - off) : size;
}
template <class T>
inline T *align_ptr(T *src, size_t align = DEFAULT_ALIGN)
{
uintptr_t x = uintptr_t(src);
uintptr_t off = x % align;
return (off) ?
reinterpret_cast<T *>(x + align - off) :
src;
}
template <class T>
inline bool is_ptr_aligned(T *src, size_t align = DEFAULT_ALIGN)
{
ptrdiff_t x = ptrdiff_t(src);
return !(x % align);
}
template <class T>
inline T *lsp_malloc(size_t count = 1)
{
return static_cast<T *>(::malloc(sizeof(T) * count));
}
/** Allocate aligned pointer
*
* @param ptr reference to pointer to store allocated pointer for future free() operation
* @param count number of elements to allocate
* @param align alignment, should be power of 2, by default DEFAULT_ALIGN
* @return aligned pointer as a result of alignment of ptr to align boundary or NULL if allocation failed
* @example
* void *x = NULL;
* float *a = alloc_aligned<float>(x, 1000); // Allocate 1000 floats aligned to DEFAULT_ALIGN boundary
* if (a == NULL)
* return ERROR;
* // Do some stuff
* free_aligned(x);
* a = NULL;
*/
template <class T, class P>
inline T *alloc_aligned(P * &ptr, size_t count, size_t align=DEFAULT_ALIGN)
{
// Check for power of 2
if ((!align) || (align & (align-1)))
return NULL;
// Allocate data
void *p = ::malloc((count * sizeof(T)) + align);
if (p == NULL)
return NULL;
// Store pointer
ptr = reinterpret_cast<P *>(p);
// Return aligned pointer
ptrdiff_t x = ptrdiff_t(p);
ptrdiff_t mask = align-1;
return reinterpret_cast<T *>((x & mask) ? ((x + align)&(~mask)) : x);
}
/** Free aligned pointer and write NULL to it
*
* @param ptr pointer to free
*/
template <class P>
inline void free_aligned(P * &ptr)
{
if (ptr == NULL)
return;
P *tptr = ptr;
ptr = NULL;
::free(tptr);
}
/**
* Seed the address
* @param ptr address to seed
* @return seed value
*/
inline uint32_t seed_addr(const void *ptr)
{
#if defined(ARCH_I386)
return uint32_t(ptr);
#elif defined(ARCH_X86_64)
return uint32_t(ptrdiff_t(ptr)) ^ uint32_t(ptrdiff_t(ptr) >> 32);
#else
return uint32_t(ptrdiff_t(ptr));
#endif
}
}
#endif /* LSP_PLUG_IN_COMMON_ALLOC_H_ */
|