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 // ManualConstructor statically-allocates space in which to store some
      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
      8 // for memory management optimizations, where you want to initialize and
      9 // destroy an object multiple times but only allocate it once.
     10 //
     11 // (When I say ManualConstructor statically allocates space, I mean that
     12 // the ManualConstructor object itself is forced to be the right size.)
     13 //
     14 // For example usage, check out base/containers/small_map.h.
     15 
     16 #ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
     17 #define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
     18 
     19 #include <stddef.h>
     20 
     21 #include "base/memory/aligned_memory.h"
     22 
     23 namespace base {
     24 
     25 template <typename Type>
     26 class ManualConstructor {
     27  public:
     28   // 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   // constructors or destructors.  And, anyway, the whole point of this
     31   // class is to bypass these.
     32 
     33   // Support users creating arrays of ManualConstructor<>s.  This ensures that
     34   // the array itself has the correct alignment.
     35   static void* operator new[](size_t size) {
     36 #if defined(COMPILER_MSVC)
     37     return AlignedAlloc(size, __alignof(Type));
     38 #else
     39     return AlignedAlloc(size, __alignof__(Type));
     40 #endif
     41   }
     42   static void operator delete[](void* mem) {
     43     AlignedFree(mem);
     44   }
     45 
     46   inline Type* get() {
     47     return space_.template data_as<Type>();
     48   }
     49   inline const Type* get() const  {
     50     return space_.template data_as<Type>();
     51   }
     52 
     53   inline Type* operator->() { return get(); }
     54   inline const Type* operator->() const { return get(); }
     55 
     56   inline Type& operator*() { return *get(); }
     57   inline const Type& operator*() const { return *get(); }
     58 
     59   // You can pass up to eight constructor arguments as arguments of Init().
     60   inline void Init() {
     61     new(space_.void_data()) Type;
     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   }
    110 
    111   inline void Destroy() {
    112     get()->~Type();
    113   }
    114 
    115  private:
    116 #if defined(COMPILER_MSVC)
    117   AlignedMemory<sizeof(Type), __alignof(Type)> space_;
    118 #else
    119   AlignedMemory<sizeof(Type), __alignof__(Type)> space_;
    120 #endif
    121 };
    122 
    123 }  // namespace base
    124 
    125 #endif  // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
    126