Home | History | Annotate | Download | only in memory
      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 unique_ptr:
     30 //
     31 //   std::unique_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 
     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 unique_ptr. E.g., use as
    108 //   std::unique_ptr<Foo, base::AlignedFreeDeleter> foo;
    109 struct AlignedFreeDeleter {
    110   inline void operator()(void* ptr) const {
    111     AlignedFree(ptr);
    112   }
    113 };
    114 
    115 }  // namespace base
    116 
    117 #endif  // BASE_MEMORY_ALIGNED_MEMORY_H_
    118