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 
5 // AlignedMemory is a POD type that gives you a portable way to specify static
6 // or local stack data of a given alignment and size. For example, if you need
7 // static storage for a class, but you want manual control over when the object
8 // is constructed and destructed (you don't want static initialization and
9 // destruction), use AlignedMemory:
10 //
11 //   static AlignedMemory<sizeof(MyClass), ALIGNOF(MyClass)> my_class;
12 //
13 //   // ... at runtime:
14 //   new(my_class.void_data()) MyClass();
15 //
16 //   // ... use it:
17 //   MyClass* mc = my_class.data_as<MyClass>();
18 //
19 //   // ... later, to destruct my_class:
20 //   my_class.data_as<MyClass>()->MyClass::~MyClass();
21 //
22 // Alternatively, a runtime sized aligned allocation can be created:
23 //
24 //   float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
25 //
26 //   // ... later, to release the memory:
27 //   AlignedFree(my_array);
28 //
29 // Or using scoped_ptr:
30 //
31 //   scoped_ptr<float, AlignedFreeDeleter> my_array(
32 //       static_cast<float*>(AlignedAlloc(size, alignment)));
33 
34 #ifndef BASE_MEMORY_ALIGNED_MEMORY_H_
35 #define BASE_MEMORY_ALIGNED_MEMORY_H_
36 
37 #include <stddef.h>
38 #include <stdint.h>
39 
40 #include "base/base_export.h"
41 #include "base/compiler_specific.h"
42 
43 #if defined(COMPILER_MSVC)
44 #include <malloc.h>
45 #else
46 #include <stdlib.h>
47 #endif
48 
49 namespace base {
50 
51 // AlignedMemory is specialized for all supported alignments.
52 // Make sure we get a compiler error if someone uses an unsupported alignment.
53 template <size_t Size, size_t ByteAlignment>
54 struct AlignedMemory {};
55 
56 #define BASE_DECL_ALIGNED_MEMORY(byte_alignment)                              \
57   template <size_t Size>                                                      \
58   class AlignedMemory<Size, byte_alignment> {                                 \
59    public:                                                                    \
60     ALIGNAS(byte_alignment) uint8_t data_[Size];                              \
61     void* void_data() { return static_cast<void*>(data_); }                   \
62     const void* void_data() const { return static_cast<const void*>(data_); } \
63     template <typename Type>                                                  \
64     Type* data_as() {                                                         \
65       return static_cast<Type*>(void_data());                                 \
66     }                                                                         \
67     template <typename Type>                                                  \
68     const Type* data_as() const {                                             \
69       return static_cast<const Type*>(void_data());                           \
70     }                                                                         \
71                                                                               \
72    private:                                                                   \
73     void* operator new(size_t);                                               \
74     void operator delete(void*);                                              \
75   }
76 
77 // Specialization for all alignments is required because MSVC (as of VS 2008)
78 // does not understand ALIGNAS(ALIGNOF(Type)) or ALIGNAS(template_param).
79 // Greater than 4096 alignment is not supported by some compilers, so 4096 is
80 // the maximum specified here.
81 BASE_DECL_ALIGNED_MEMORY(1);
82 BASE_DECL_ALIGNED_MEMORY(2);
83 BASE_DECL_ALIGNED_MEMORY(4);
84 BASE_DECL_ALIGNED_MEMORY(8);
85 BASE_DECL_ALIGNED_MEMORY(16);
86 BASE_DECL_ALIGNED_MEMORY(32);
87 BASE_DECL_ALIGNED_MEMORY(64);
88 BASE_DECL_ALIGNED_MEMORY(128);
89 BASE_DECL_ALIGNED_MEMORY(256);
90 BASE_DECL_ALIGNED_MEMORY(512);
91 BASE_DECL_ALIGNED_MEMORY(1024);
92 BASE_DECL_ALIGNED_MEMORY(2048);
93 BASE_DECL_ALIGNED_MEMORY(4096);
94 
95 #undef BASE_DECL_ALIGNED_MEMORY
96 
97 BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
98 
AlignedFree(void * ptr)99 inline void AlignedFree(void* ptr) {
100 #if defined(COMPILER_MSVC)
101   _aligned_free(ptr);
102 #else
103   free(ptr);
104 #endif
105 }
106 
107 // Deleter for use with scoped_ptr. E.g., use as
108 //   scoped_ptr<Foo, base::AlignedFreeDeleter> foo;
109 struct AlignedFreeDeleter {
operatorAlignedFreeDeleter110   inline void operator()(void* ptr) const {
111     AlignedFree(ptr);
112   }
113 };
114 
115 }  // namespace base
116 
117 #endif  // BASE_MEMORY_ALIGNED_MEMORY_H_
118