blob: 99ecd294889b0708129aa639e4ac5569a25bc045 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_UTIL_ALIGNED_ALLOC_H_
#define TOOLS_UTIL_ALIGNED_ALLOC_H_
#ifdef __APPLE__
#include <Availability.h>
#endif
#include <cstdlib>
#define IMPL_ALIGNED_ALLOC_CXX17 1
#define IMPL_ALIGNED_ALLOC_WIN32 2
#define IMPL_ALIGNED_ALLOC_POSIX 3
#ifndef IMPL_ALIGNED_ALLOC
#ifdef _WIN32
#define IMPL_ALIGNED_ALLOC IMPL_ALIGNED_ALLOC_WIN32
#elif defined(__APPLE__)
// Note that aligned_alloc() is only available at runtime starting from
// OSX 10.15, so use posix_memalign() instead which is more portable.
#define IMPL_ALIGNED_ALLOC IMPL_ALIGNED_ALLOC_POSIX
#else
#define IMPL_ALIGNED_ALLOC IMPL_ALIGNED_ALLOC_CXX17
#endif
#endif
#if IMPL_ALIGNED_ALLOC == IMPL_ALIGNED_ALLOC_WIN32
#include <malloc.h> // for _aligned_malloc() and _aligned_free()
#endif
#if IMPL_ALIGNED_ALLOC == IMPL_ALIGNED_ALLOC_POSIX
#include "base/logging.h" // for CHECK()
#endif
// AlignedAlloc<N> provides Alloc() and Free() methods that can be
// used to allocate and release blocks of heap memory aligned with
// N bytes.
//
// The implementation uses std::aligned_alloc() when it is available,
// or uses fallbacks otherwise. On Win32, _aligned_malloc() and
// _aligned_free() are used, while for MacOS releases, ::posix_memaloc()
// is used.
template <size_t ALIGNMENT>
struct AlignedAlloc {
static void* Alloc(size_t size) {
static_assert((ALIGNMENT & (ALIGNMENT - 1)) == 0,
"ALIGNMENT must be a power of 2");
#if IMPL_ALIGNED_ALLOC == IMPL_ALIGNED_ALLOC_WIN32
return _aligned_malloc(size, ALIGNMENT);
#elif IMPL_ALIGNED_ALLOC == IMPL_ALIGNED_ALLOC_POSIX
void* ptr = nullptr;
CHECK(!posix_memalign(&ptr, ALIGNMENT, size));
return ptr;
#else // IMPL_ALIGNED_ALLOC_CXX17
return std::aligned_alloc(ALIGNMENT, size);
#endif
}
static void Free(void* block) {
#if IMPL_ALIGNED_ALLOC == IMPL_ALIGNED_ALLOC_WIN32
_aligned_free(block);
#elif IMPL_ALIGNED_ALLOC == IMPL_ALIGNED_ALLOC_POSIX
return ::free(block);
#else
// Allocation came from std::aligned_alloc()
return std::free(block);
#endif
}
};
#endif // TOOLS_UTIL_ALIGNED_ALLOC_H_