text: // Copyright (c) 2012 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 BASE_MEMORY_ALIGNED_MEMORY_H_
  #define BASE_MEMORY_ALIGNED_MEMORY_H_
  
  #include <stddef.h>
  #include <stdint.h>
  
  #include <type_traits>
  
  #include "base/base_export.h"
  #include "base/compiler_specific.h"
  #include "base/logging.h"
  #include "base/process/process_metrics.h"
  #include "build/build_config.h"
  
  #if defined(COMPILER_MSVC)
  #include <malloc.h>
  #else
  #include <stdlib.h>
  #endif
  
  // A runtime sized aligned allocation can be created:
  //
  //   float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
  //
  //   // ... later, to release the memory:
  //   AlignedFree(my_array);
  //
  // Or using unique_ptr:
  //
  //   std::unique_ptr<float, AlignedFreeDeleter> my_array(
  //       static_cast<float*>(AlignedAlloc(size, alignment)));
  
  namespace base {
  
  // This can be replaced with std::aligned_alloc when we have C++17.
  // Caveat: std::aligned_alloc requires the size parameter be an integral
  // multiple of alignment.
  BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
  
  inline void AlignedFree(void* ptr) {
  #if defined(COMPILER_MSVC)
    _aligned_free(ptr);
  #else
    free(ptr);
  #endif
  }
  
  // Deleter for use with unique_ptr. E.g., use as
  //   std::unique_ptr<Foo, base::AlignedFreeDeleter> foo;
  struct AlignedFreeDeleter {
    inline void operator()(void* ptr) const {
      AlignedFree(ptr);
    }
  };
  
  #ifndef __has_builtin
  #define __has_builtin(x) 0  // Compatibility with non-clang compilers.
  #endif
  
  inline bool IsAligned(uintptr_t val, size_t alignment) {
    // If the compiler supports builtin alignment checks prefer them.
  #if __has_builtin(__builtin_is_aligned)
    return __builtin_is_aligned(val, alignment);
  #else
    DCHECK(!((alignment - 1) & alignment))
        << alignment << " is not a power of two";
    return (val & (alignment - 1)) == 0;
  #endif
  }
  
  inline bool IsAligned(void* val, size_t alignment) {
    return IsAligned(reinterpret_cast<uintptr_t>(val), alignment);
  }
  
  template <typename Type>
  inline bool IsPageAligned(Type val) {
    static_assert(std::is_integral<Type>::value || std::is_pointer<Type>::value,
                  "Integral or pointer type required");
    return base::IsAligned(val, base::GetPageSize());
  }
  
  }  // namespace base
  
  #endif  // BASE_MEMORY_ALIGNED_MEMORY_H_
  