aligned_memory.h 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_MEMORY_ALIGNED_MEMORY_H_
  5. #define BASE_MEMORY_ALIGNED_MEMORY_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <type_traits>
  9. #include "base/base_export.h"
  10. #include "base/bits.h"
  11. #include "base/check.h"
  12. #include "base/process/process_metrics.h"
  13. #include "build/build_config.h"
  14. #if defined(COMPILER_MSVC)
  15. #include <malloc.h>
  16. #else
  17. #include <stdlib.h>
  18. #endif
  19. // A runtime sized aligned allocation can be created:
  20. //
  21. // float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
  22. //
  23. // // ... later, to release the memory:
  24. // AlignedFree(my_array);
  25. //
  26. // Or using unique_ptr:
  27. //
  28. // std::unique_ptr<float, AlignedFreeDeleter> my_array(
  29. // static_cast<float*>(AlignedAlloc(size, alignment)));
  30. namespace base {
  31. // This can be replaced with std::aligned_alloc when we have C++17.
  32. // Caveat: std::aligned_alloc requires the size parameter be an integral
  33. // multiple of alignment.
  34. BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
  35. inline void AlignedFree(void* ptr) {
  36. #if defined(COMPILER_MSVC)
  37. _aligned_free(ptr);
  38. #else
  39. free(ptr);
  40. #endif
  41. }
  42. // Deleter for use with unique_ptr. E.g., use as
  43. // std::unique_ptr<Foo, base::AlignedFreeDeleter> foo;
  44. struct AlignedFreeDeleter {
  45. inline void operator()(void* ptr) const {
  46. AlignedFree(ptr);
  47. }
  48. };
  49. #ifdef __has_builtin
  50. #define SUPPORTS_BUILTIN_IS_ALIGNED (__has_builtin(__builtin_is_aligned))
  51. #else
  52. #define SUPPORTS_BUILTIN_IS_ALIGNED 0
  53. #endif
  54. inline bool IsAligned(uintptr_t val, size_t alignment) {
  55. // If the compiler supports builtin alignment checks prefer them.
  56. #if SUPPORTS_BUILTIN_IS_ALIGNED
  57. return __builtin_is_aligned(val, alignment);
  58. #else
  59. DCHECK(bits::IsPowerOfTwo(alignment)) << alignment << " is not a power of 2";
  60. return (val & (alignment - 1)) == 0;
  61. #endif
  62. }
  63. #undef SUPPORTS_BUILTIN_IS_ALIGNED
  64. inline bool IsAligned(const void* val, size_t alignment) {
  65. return IsAligned(reinterpret_cast<uintptr_t>(val), alignment);
  66. }
  67. template <typename Type>
  68. inline bool IsPageAligned(Type val) {
  69. static_assert(std::is_integral<Type>::value || std::is_pointer<Type>::value,
  70. "Integral or pointer type required");
  71. return IsAligned(val, GetPageSize());
  72. }
  73. } // namespace base
  74. #endif // BASE_MEMORY_ALIGNED_MEMORY_H_