AWS SDK for C++  1.8.24
AWS SDK for C++
AWSMemory.h
Go to the documentation of this file.
1 
6 #pragma once
7 
11 
12 #include <memory>
13 #include <cstdlib>
14 #include <algorithm>
15 #include <type_traits>
16 
17 struct aws_allocator;
18 
19 namespace Aws
20 {
21  namespace Utils
22  {
23  namespace Memory
24  {
29 
34 
39 
40  } // namespace Memory
41  } // namespace Utils
42 
47  AWS_CORE_API void* Malloc(const char* allocationTag, size_t allocationSize);
48 
53  AWS_CORE_API void Free(void* memoryPtr);
54 
55  AWS_CORE_API aws_allocator* get_aws_allocator();
56 
61  template<typename T, typename ...ArgTypes>
62  T* New(const char* allocationTag, ArgTypes&&... args)
63  {
64  void *rawMemory = Malloc(allocationTag, sizeof(T));
65  // http://stackoverflow.com/questions/6783993/placement-new-and-delete
66  T *constructedMemory = new (rawMemory) T(std::forward<ArgTypes>(args)...);
67  return constructedMemory;
68  }
69 /*
70  * dynamic_cast of all sorts do not work on MSVC if RTTI is turned off.
71  * This means that deleting an object via a pointer to one of its polymorphic base types that do not point to the
72  * address of their concrete class will result in undefined behavior.
73  * Example:
74  * struct Foo : InterfaceA, InterfaceB {};
75  * Aws::Delete(pointerToInterfaceB);
76  */
77 #if defined(_MSC_VER) && !defined(_CPPRTTI)
78  template<typename T>
79  void Delete(T* pointerToT)
80  {
81  if (pointerToT == nullptr)
82  {
83  return;
84  }
85  pointerToT->~T();
86  Free(pointerToT);
87  }
88 #else
89 
93  template<typename T>
94  typename std::enable_if<!std::is_polymorphic<T>::value>::type Delete(T* pointerToT)
95  {
96  if (pointerToT == nullptr)
97  {
98  return;
99  }
100  //http://stackoverflow.com/questions/6783993/placement-new-and-delete
101  pointerToT->~T();
102  Free(pointerToT);
103  }
104 
105  template<typename T>
106  typename std::enable_if<std::is_polymorphic<T>::value>::type Delete(T* pointerToT)
107  {
108  if (pointerToT == nullptr)
109  {
110  return;
111  }
112  // deal with deleting objects that implement multiple interfaces
113  // see casting to pointer to void in http://en.cppreference.com/w/cpp/language/dynamic_cast
114  // https://stackoverflow.com/questions/8123776/are-there-practical-uses-for-dynamic-casting-to-void-pointer
115  // NOTE: on some compilers, calling the destructor before doing the dynamic_cast affects how calculation of
116  // the address of the most derived class.
117  void* mostDerivedT = dynamic_cast<void*>(pointerToT);
118  pointerToT->~T();
119  Free(mostDerivedT);
120  }
121 #endif // _CPPRTTI
122 
123  template<typename T>
125  {
126  return std::is_class<T>::value;
127  }
128 
129  template<typename T>
131  {
132  return !std::is_trivially_destructible<T>::value;
133  }
134 
139  template<typename T>
140  T* NewArray(std::size_t amount, const char* allocationTag)
141  {
142  if (amount > 0)
143  {
144  bool constructMembers = ShouldConstructArrayMembers<T>();
145  bool trackMemberCount = ShouldDestroyArrayMembers<T>();
146 
147  // if we need to remember the # of items in the array (because we need to call their destructors) then allocate extra memory and keep the # of items in the extra slot
148  std::size_t allocationSize = amount * sizeof(T);
149 #if defined(_MSC_VER) && _MSC_VER < 1900
150  std::size_t headerSize = (std::max)(sizeof(std::size_t), __alignof(T));
151 #else
152  std::size_t headerSize = (std::max)(sizeof(std::size_t), alignof(T));
153 #endif
154 
155  if (trackMemberCount)
156  {
157  allocationSize += headerSize;
158  }
159 
160  void* rawMemory = Malloc(allocationTag, allocationSize);
161  T* pointerToT = nullptr;
162 
163  if (trackMemberCount)
164  {
165  std::size_t* pointerToAmount = reinterpret_cast<std::size_t*>(rawMemory);
166  *pointerToAmount = amount;
167  pointerToT = reinterpret_cast<T*>(reinterpret_cast<char*>(pointerToAmount) + headerSize);
168 
169  }
170  else
171  {
172  pointerToT = reinterpret_cast<T*>(rawMemory);
173  }
174 
175  if (constructMembers)
176  {
177  for (std::size_t i = 0; i < amount; ++i)
178  {
179  new (pointerToT + i) T;
180  }
181  }
182 
183  return pointerToT;
184  }
185 
186  return nullptr;
187  }
188 
193  template<typename T>
194  void DeleteArray(T* pointerToTArray)
195  {
196  if (pointerToTArray == nullptr)
197  {
198  return;
199  }
200 
201  bool destroyMembers = ShouldDestroyArrayMembers<T>();
202  void* rawMemory = nullptr;
203 
204  if (destroyMembers)
205  {
206 #if defined(_MSC_VER) && _MSC_VER < 1900
207  std::size_t headerSize = (std::max)(sizeof(std::size_t), __alignof(T));
208 #else
209  std::size_t headerSize = (std::max)(sizeof(std::size_t), alignof(T));
210 #endif
211 
212  std::size_t *pointerToAmount = reinterpret_cast<std::size_t*>(reinterpret_cast<char*>(pointerToTArray) - headerSize);
213  std::size_t amount = *pointerToAmount;
214 
215  for (std::size_t i = amount; i > 0; --i)
216  {
217  (pointerToTArray + i - 1)->~T();
218  }
219  rawMemory = reinterpret_cast<void *>(pointerToAmount);
220  }
221  else
222  {
223  rawMemory = reinterpret_cast<void *>(pointerToTArray);
224  }
225 
226  Free(rawMemory);
227  }
228 
232  template<typename T>
233  struct Deleter
234  {
235  Deleter() {}
236 
237  template<class U, class = typename std::enable_if<std::is_convertible<U *, T *>::value, void>::type>
239  {
240  }
241 
242  void operator()(T *pointerToT) const
243  {
244  static_assert(0 < sizeof(T), "can't delete an incomplete type");
245  Aws::Delete(pointerToT);
246  }
247  };
248 
249  template< typename T > using UniquePtr = std::unique_ptr< T, Deleter< T > >;
250 
255  template<typename T, typename ...ArgTypes>
256  UniquePtr<T> MakeUnique(const char* allocationTag, ArgTypes&&... args)
257  {
258  return UniquePtr<T>(Aws::New<T>(allocationTag, std::forward<ArgTypes>(args)...));
259  }
260 
261  template<typename T>
263  {
265 
266  template<class U, class = typename std::enable_if<std::is_convertible<U *, T *>::value, void>::type>
268  {
269  }
270 
271  void operator()(T *pointerToTArray) const
272  {
273  static_assert(0 < sizeof(T), "can't delete an incomplete type");
274  Aws::DeleteArray(pointerToTArray);
275  }
276  };
277 
278  template< typename T > using UniqueArrayPtr = std::unique_ptr< T, ArrayDeleter< T > >;
279 
284  template<typename T, typename ...ArgTypes>
285  UniqueArrayPtr<T> MakeUniqueArray(std::size_t amount, const char* allocationTag, ArgTypes&&... args)
286  {
287  return UniqueArrayPtr<T>(Aws::NewArray<T>(amount, allocationTag, std::forward<ArgTypes>(args)...));
288  }
289 
290 } // namespace Aws
291 
void DeleteArray(T *pointerToTArray)
Definition: AWSMemory.h:194
bool ShouldConstructArrayMembers()
Definition: AWSMemory.h:124
bool ShouldDestroyArrayMembers()
Definition: AWSMemory.h:130
ArrayDeleter(const ArrayDeleter< U > &)
Definition: AWSMemory.h:267
UniquePtr< T > MakeUnique(const char *allocationTag, ArgTypes &&... args)
Definition: AWSMemory.h:256
T * New(const char *allocationTag, ArgTypes &&... args)
Definition: AWSMemory.h:62
AWS_CORE_API aws_allocator * get_aws_allocator()
AWS_CORE_API void ShutdownAWSMemorySystem(void)
UniqueArrayPtr< T > MakeUniqueArray(std::size_t amount, const char *allocationTag, ArgTypes &&... args)
Definition: AWSMemory.h:285
std::unique_ptr< T, ArrayDeleter< T > > UniqueArrayPtr
Definition: AWSMemory.h:278
AWS_CORE_API void InitializeAWSMemorySystem(MemorySystemInterface &memorySystem)
AWS_CORE_API MemorySystemInterface * GetMemorySystem()
AWS_CORE_API void Free(void *memoryPtr)
std::unique_ptr< T, Deleter< T > > UniquePtr
Definition: AWSMemory.h:249
void operator()(T *pointerToTArray) const
Definition: AWSMemory.h:271
T * NewArray(std::size_t amount, const char *allocationTag)
Definition: AWSMemory.h:140
std::enable_if<!std::is_polymorphic< T >::value >::type Delete(T *pointerToT)
Definition: AWSMemory.h:94
AWS_CORE_API void * Malloc(const char *allocationTag, size_t allocationSize)
#define AWS_CORE_API
Definition: Core_EXPORTS.h:25
Deleter(const Deleter< U > &)
Definition: AWSMemory.h:238
void operator()(T *pointerToT) const
Definition: AWSMemory.h:242