463591663c
Some compilers support C++17 even on targets that lack required functions. Projects that want to force C++17 will then run into a problem with std::aligned_alloc not existing on those targets, so it needs to be explicitly checked for. The alternative is to simply never use it even when it would be available.
66 lines
1.4 KiB
C++
66 lines
1.4 KiB
C++
|
|
#include "config.h"
|
|
|
|
#include "almalloc.h"
|
|
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#ifdef HAVE_MALLOC_H
|
|
#include <malloc.h>
|
|
#endif
|
|
|
|
|
|
void *al_malloc(size_t alignment, size_t size)
|
|
{
|
|
assert((alignment & (alignment-1)) == 0);
|
|
alignment = std::max(alignment, alignof(std::max_align_t));
|
|
|
|
#if defined(HAVE_STD_ALIGNED_ALLOC)
|
|
size = (size+(alignment-1))&~(alignment-1);
|
|
return std::aligned_alloc(alignment, size);
|
|
#elif defined(HAVE_POSIX_MEMALIGN)
|
|
void *ret;
|
|
if(posix_memalign(&ret, alignment, size) == 0)
|
|
return ret;
|
|
return nullptr;
|
|
#elif defined(HAVE__ALIGNED_MALLOC)
|
|
return _aligned_malloc(size, alignment);
|
|
#else
|
|
auto *ret = static_cast<char*>(std::malloc(size+alignment));
|
|
if(ret != nullptr)
|
|
{
|
|
*(ret++) = 0x00;
|
|
while((reinterpret_cast<uintptr_t>(ret)&(alignment-1)) != 0)
|
|
*(ret++) = 0x55;
|
|
}
|
|
return ret;
|
|
#endif
|
|
}
|
|
|
|
void *al_calloc(size_t alignment, size_t size)
|
|
{
|
|
void *ret = al_malloc(alignment, size);
|
|
if(ret) std::memset(ret, 0, size);
|
|
return ret;
|
|
}
|
|
|
|
void al_free(void *ptr) noexcept
|
|
{
|
|
#if defined(HAVE_STD_ALIGNED_ALLOC) || defined(HAVE_POSIX_MEMALIGN)
|
|
std::free(ptr);
|
|
#elif defined(HAVE__ALIGNED_MALLOC)
|
|
_aligned_free(ptr);
|
|
#else
|
|
if(ptr != nullptr)
|
|
{
|
|
auto *finder = static_cast<char*>(ptr);
|
|
do {
|
|
--finder;
|
|
} while(*finder == 0x55);
|
|
std::free(finder);
|
|
}
|
|
#endif
|
|
}
|