xref: /aosp_15_r20/external/cronet/base/memory/aligned_memory.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_MEMORY_ALIGNED_MEMORY_H_
6 #define BASE_MEMORY_ALIGNED_MEMORY_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <bit>
12 #include <ostream>
13 
14 #include "base/base_export.h"
15 #include "base/check.h"
16 #include "build/build_config.h"
17 
18 #if defined(COMPILER_MSVC)
19 #include <malloc.h>
20 #else
21 #include <stdlib.h>
22 #endif
23 
24 // A runtime sized aligned allocation can be created:
25 //
26 //   float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
27 //   CHECK(reinterpret_cast<uintptr_t>(my_array) % alignment == 0);
28 //   memset(my_array, 0, size);  // fills entire object.
29 //
30 //   // ... later, to release the memory:
31 //   AlignedFree(my_array);
32 //
33 // Or using unique_ptr:
34 //
35 //   std::unique_ptr<float, AlignedFreeDeleter> my_array(
36 //       static_cast<float*>(AlignedAlloc(size, alignment)));
37 
38 namespace base {
39 
40 // Allocate memory of size `size` aligned to `alignment`.
41 //
42 // TODO(https://crbug.com/40255447): Convert usage to / convert to use
43 // `std::aligned_alloc` to the extent that it can be done (since
44 // `std::aligned_alloc` can't be used on Windows). When that happens, note that
45 // `std::aligned_alloc` requires the `size` parameter be an integral multiple of
46 // `alignment` while this implementation does not.
47 BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
48 
49 // Deallocate memory allocated by `AlignedAlloc`.
AlignedFree(void * ptr)50 inline void AlignedFree(void* ptr) {
51 #if defined(COMPILER_MSVC)
52   _aligned_free(ptr);
53 #else
54   free(ptr);
55 #endif
56 }
57 
58 // Deleter for use with unique_ptr. E.g., use as
59 //   std::unique_ptr<Foo, base::AlignedFreeDeleter> foo;
60 struct AlignedFreeDeleter {
operatorAlignedFreeDeleter61   inline void operator()(void* ptr) const {
62     AlignedFree(ptr);
63   }
64 };
65 
66 #ifdef __has_builtin
67 #define SUPPORTS_BUILTIN_IS_ALIGNED (__has_builtin(__builtin_is_aligned))
68 #else
69 #define SUPPORTS_BUILTIN_IS_ALIGNED 0
70 #endif
71 
IsAligned(uintptr_t val,size_t alignment)72 inline bool IsAligned(uintptr_t val, size_t alignment) {
73   // If the compiler supports builtin alignment checks prefer them.
74 #if SUPPORTS_BUILTIN_IS_ALIGNED
75   return __builtin_is_aligned(val, alignment);
76 #else
77   DCHECK(std::has_single_bit(alignment)) << alignment << " is not a power of 2";
78   return (val & (alignment - 1)) == 0;
79 #endif
80 }
81 
82 #undef SUPPORTS_BUILTIN_IS_ALIGNED
83 
IsAligned(const void * val,size_t alignment)84 inline bool IsAligned(const void* val, size_t alignment) {
85   return IsAligned(reinterpret_cast<uintptr_t>(val), alignment);
86 }
87 
88 }  // namespace base
89 
90 #endif  // BASE_MEMORY_ALIGNED_MEMORY_H_
91