OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // ManualConstructor statically-allocates space in which to store some | 5 // ManualConstructor statically-allocates space in which to store some |
6 // object, but does not initialize it. You can then call the constructor | 6 // object, but does not initialize it. You can then call the constructor |
7 // and destructor for the object yourself as you see fit. This is useful | 7 // and destructor for the object yourself as you see fit. This is useful |
8 // for memory management optimizations, where you want to initialize and | 8 // for memory management optimizations, where you want to initialize and |
9 // destroy an object multiple times but only allocate it once. | 9 // destroy an object multiple times but only allocate it once. |
10 // | 10 // |
11 // (When I say ManualConstructor statically allocates space, I mean that | 11 // (When I say ManualConstructor statically allocates space, I mean that |
12 // the ManualConstructor object itself is forced to be the right size.) | 12 // the ManualConstructor object itself is forced to be the right size.) |
13 // | 13 // |
14 // For example usage, check out base/containers/small_map.h. | 14 // For example usage, check out base/containers/small_map.h. |
15 | 15 |
16 #ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ | 16 #ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ |
17 #define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ | 17 #define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ |
18 | 18 |
19 #include <stddef.h> | 19 #include <stddef.h> |
20 | 20 |
| 21 #include "base/compiler_specific.h" |
21 #include "base/memory/aligned_memory.h" | 22 #include "base/memory/aligned_memory.h" |
22 | 23 |
23 namespace base { | 24 namespace base { |
24 | 25 |
25 template <typename Type> | 26 template <typename Type> |
26 class ManualConstructor { | 27 class ManualConstructor { |
27 public: | 28 public: |
28 // No constructor or destructor because one of the most useful uses of | 29 // No constructor or destructor because one of the most useful uses of |
29 // this class is as part of a union, and members of a union cannot have | 30 // this class is as part of a union, and members of a union cannot have |
30 // constructors or destructors. And, anyway, the whole point of this | 31 // constructors or destructors. And, anyway, the whole point of this |
31 // class is to bypass these. | 32 // class is to bypass these. |
32 | 33 |
33 // Support users creating arrays of ManualConstructor<>s. This ensures that | 34 // Support users creating arrays of ManualConstructor<>s. This ensures that |
34 // the array itself has the correct alignment. | 35 // the array itself has the correct alignment. |
35 static void* operator new[](size_t size) { | 36 static void* operator new[](size_t size) { |
36 #if defined(COMPILER_MSVC) | 37 return AlignedAlloc(size, ALIGNOF(Type)); |
37 return AlignedAlloc(size, __alignof(Type)); | |
38 #else | |
39 return AlignedAlloc(size, __alignof__(Type)); | |
40 #endif | |
41 } | 38 } |
42 static void operator delete[](void* mem) { | 39 static void operator delete[](void* mem) { |
43 AlignedFree(mem); | 40 AlignedFree(mem); |
44 } | 41 } |
45 | 42 |
46 inline Type* get() { | 43 inline Type* get() { |
47 return space_.template data_as<Type>(); | 44 return space_.template data_as<Type>(); |
48 } | 45 } |
49 inline const Type* get() const { | 46 inline const Type* get() const { |
50 return space_.template data_as<Type>(); | 47 return space_.template data_as<Type>(); |
51 } | 48 } |
52 | 49 |
53 inline Type* operator->() { return get(); } | 50 inline Type* operator->() { return get(); } |
54 inline const Type* operator->() const { return get(); } | 51 inline const Type* operator->() const { return get(); } |
55 | 52 |
56 inline Type& operator*() { return *get(); } | 53 inline Type& operator*() { return *get(); } |
57 inline const Type& operator*() const { return *get(); } | 54 inline const Type& operator*() const { return *get(); } |
58 | 55 |
59 // You can pass up to eight constructor arguments as arguments of Init(). | 56 template <typename... Ts> |
60 inline void Init() { | 57 inline void Init(const Ts&... params) { |
61 new(space_.void_data()) Type; | 58 new(space_.void_data()) Type(params...); |
62 } | |
63 | |
64 template <typename T1> | |
65 inline void Init(const T1& p1) { | |
66 new(space_.void_data()) Type(p1); | |
67 } | |
68 | |
69 template <typename T1, typename T2> | |
70 inline void Init(const T1& p1, const T2& p2) { | |
71 new(space_.void_data()) Type(p1, p2); | |
72 } | |
73 | |
74 template <typename T1, typename T2, typename T3> | |
75 inline void Init(const T1& p1, const T2& p2, const T3& p3) { | |
76 new(space_.void_data()) Type(p1, p2, p3); | |
77 } | |
78 | |
79 template <typename T1, typename T2, typename T3, typename T4> | |
80 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { | |
81 new(space_.void_data()) Type(p1, p2, p3, p4); | |
82 } | |
83 | |
84 template <typename T1, typename T2, typename T3, typename T4, typename T5> | |
85 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, | |
86 const T5& p5) { | |
87 new(space_.void_data()) Type(p1, p2, p3, p4, p5); | |
88 } | |
89 | |
90 template <typename T1, typename T2, typename T3, typename T4, typename T5, | |
91 typename T6> | |
92 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, | |
93 const T5& p5, const T6& p6) { | |
94 new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6); | |
95 } | |
96 | |
97 template <typename T1, typename T2, typename T3, typename T4, typename T5, | |
98 typename T6, typename T7> | |
99 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, | |
100 const T5& p5, const T6& p6, const T7& p7) { | |
101 new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7); | |
102 } | |
103 | |
104 template <typename T1, typename T2, typename T3, typename T4, typename T5, | |
105 typename T6, typename T7, typename T8> | |
106 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, | |
107 const T5& p5, const T6& p6, const T7& p7, const T8& p8) { | |
108 new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7, p8); | |
109 } | 59 } |
110 | 60 |
111 inline void Destroy() { | 61 inline void Destroy() { |
112 get()->~Type(); | 62 get()->~Type(); |
113 } | 63 } |
114 | 64 |
115 private: | 65 private: |
116 #if defined(COMPILER_MSVC) | 66 AlignedMemory<sizeof(Type), ALIGNOF(Type)> space_; |
117 AlignedMemory<sizeof(Type), __alignof(Type)> space_; | |
118 #else | |
119 AlignedMemory<sizeof(Type), __alignof__(Type)> space_; | |
120 #endif | |
121 }; | 67 }; |
122 | 68 |
123 } // namespace base | 69 } // namespace base |
124 | 70 |
125 #endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ | 71 #endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ |
OLD | NEW |