lazy-instance.h 9.14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// The LazyInstance<Type, Traits> class manages a single instance of Type,
// which will be lazily created on the first time it's accessed.  This class is
// useful for places you would normally use a function-level static, but you
// need to have guaranteed thread-safety.  The Type constructor will only ever
// be called once, even if two threads are racing to create the object.  Get()
// and Pointer() will always return the same, completely initialized instance.
//
// LazyInstance is completely thread safe, assuming that you create it safely.
// The class was designed to be POD initialized, so it shouldn't require a
// static constructor.  It really only makes sense to declare a LazyInstance as
// a global variable using the LAZY_INSTANCE_INITIALIZER initializer.
//
// LazyInstance is similar to Singleton, except it does not have the singleton
// property.  You can have multiple LazyInstance's of the same type, and each
// will manage a unique instance.  It also preallocates the space for Type, as
// to avoid allocating the Type instance on the heap.  This may help with the
// performance of creating the instance, and reducing heap fragmentation.  This
// requires that Type be a complete type so we can determine the size. See
// notes for advanced users below for more explanations.
//
// Example usage:
//   static LazyInstance<MyClass>::type my_instance = LAZY_INSTANCE_INITIALIZER;
//   void SomeMethod() {
//     my_instance.Get().SomeMethod();  // MyClass::SomeMethod()
//
//     MyClass* ptr = my_instance.Pointer();
//     ptr->DoDoDo();  // MyClass::DoDoDo
//   }
//
// Additionally you can override the way your instance is constructed by
// providing your own trait:
// Example usage:
//   struct MyCreateTrait {
//     static void Construct(MyClass* allocated_ptr) {
//       new (allocated_ptr) MyClass(/* extra parameters... */);
//     }
//   };
//   static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
//      LAZY_INSTANCE_INITIALIZER;
//
68 69 70 71 72 73
// WARNINGS:
// - This implementation of LazyInstance is NOT THREAD-SAFE by default. See
//   ThreadSafeInitOnceTrait declared below for that.
// - Lazy initialization comes with a cost. Make sure that you don't use it on
//   critical path. Consider adding your initialization code to a function
//   which is explicitly called once.
74
//
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
// Notes for advanced users:
// LazyInstance can actually be used in two different ways:
//
// - "Static mode" which is the default mode since it is the most efficient
//   (no extra heap allocation). In this mode, the instance is statically
//   allocated (stored in the global data section at compile time).
//   The macro LAZY_STATIC_INSTANCE_INITIALIZER (= LAZY_INSTANCE_INITIALIZER)
//   must be used to initialize static lazy instances.
//
// - "Dynamic mode". In this mode, the instance is dynamically allocated and
//   constructed (using new) by default. This mode is useful if you have to
//   deal with some code already allocating the instance for you (e.g.
//   OS::Mutex() which returns a new private OS-dependent subclass of Mutex).
//   The macro LAZY_DYNAMIC_INSTANCE_INITIALIZER must be used to initialize
//   dynamic lazy instances.

#ifndef V8_LAZY_INSTANCE_H_
#define V8_LAZY_INSTANCE_H_

94
#include "checks.h"
95 96 97 98 99
#include "once.h"

namespace v8 {
namespace internal {

100
#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, { {} } }
101 102 103 104 105 106 107 108 109 110 111 112 113 114
#define LAZY_DYNAMIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, 0 }

// Default to static mode.
#define LAZY_INSTANCE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER


template <typename T>
struct LeakyInstanceTrait {
  static void Destroy(T* /* instance */) {}
};


// Traits that define how an instance is allocated and accessed.

115

116 117
template <typename T>
struct StaticallyAllocatedInstanceTrait {
118 119 120 121 122 123
  // 16-byte alignment fallback to be on the safe side here.
  struct V8_ALIGNAS(T, 16) StorageType {
    char x[sizeof(T)];
  };

  STATIC_ASSERT(V8_ALIGNOF(StorageType) >= V8_ALIGNOF(T));
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

  static T* MutableInstance(StorageType* storage) {
    return reinterpret_cast<T*>(storage);
  }

  template <typename ConstructTrait>
  static void InitStorageUsingTrait(StorageType* storage) {
    ConstructTrait::Construct(MutableInstance(storage));
  }
};


template <typename T>
struct DynamicallyAllocatedInstanceTrait {
  typedef T* StorageType;

  static T* MutableInstance(StorageType* storage) {
    return *storage;
  }

  template <typename CreateTrait>
  static void InitStorageUsingTrait(StorageType* storage) {
    *storage = CreateTrait::Create();
  }
};


template <typename T>
struct DefaultConstructTrait {
  // Constructs the provided object which was already allocated.
  static void Construct(T* allocated_ptr) {
    new(allocated_ptr) T();
  }
};


template <typename T>
struct DefaultCreateTrait {
  static T* Create() {
    return new T();
  }
};


168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
struct ThreadSafeInitOnceTrait {
  template <typename Function, typename Storage>
  static void Init(OnceType* once, Function function, Storage storage) {
    CallOnce(once, function, storage);
  }
};


// Initialization trait for users who don't care about thread-safety.
struct SingleThreadInitOnceTrait {
  template <typename Function, typename Storage>
  static void Init(OnceType* once, Function function, Storage storage) {
    if (*once == ONCE_STATE_UNINITIALIZED) {
      function(storage);
      *once = ONCE_STATE_DONE;
    }
  }
};


188 189
// TODO(pliard): Handle instances destruction (using global destructors).
template <typename T, typename AllocationTrait, typename CreateTrait,
190
          typename InitOnceTrait, typename DestroyTrait  /* not used yet. */>
191 192 193 194 195 196 197 198 199 200
struct LazyInstanceImpl {
 public:
  typedef typename AllocationTrait::StorageType StorageType;

 private:
  static void InitInstance(StorageType* storage) {
    AllocationTrait::template InitStorageUsingTrait<CreateTrait>(storage);
  }

  void Init() const {
201 202 203 204
    InitOnceTrait::Init(
        &once_,
        // Casts to void* are needed here to avoid breaking strict aliasing
        // rules.
205
        reinterpret_cast<void(*)(void*)>(&InitInstance),  // NOLINT
206
        reinterpret_cast<void*>(&storage_));
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
  }

 public:
  T* Pointer() {
    Init();
    return AllocationTrait::MutableInstance(&storage_);
  }

  const T& Get() const {
    Init();
    return *AllocationTrait::MutableInstance(&storage_);
  }

  mutable OnceType once_;
  // Note that the previous field, OnceType, is an AtomicWord which guarantees
222 223
  // 4-byte alignment of the storage field below. If compiling with GCC (>4.2),
  // the LAZY_ALIGN macro above will guarantee correctness for any alignment.
224 225 226 227 228 229
  mutable StorageType storage_;
};


template <typename T,
          typename CreateTrait = DefaultConstructTrait<T>,
230
          typename InitOnceTrait = SingleThreadInitOnceTrait,
231 232
          typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyStaticInstance {
233 234
  typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
      CreateTrait, InitOnceTrait, DestroyTrait> type;
235 236 237 238 239
};


template <typename T,
          typename CreateTrait = DefaultConstructTrait<T>,
240
          typename InitOnceTrait = SingleThreadInitOnceTrait,
241 242 243
          typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyInstance {
  // A LazyInstance is a LazyStaticInstance.
244 245
  typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
      DestroyTrait>::type type;
246 247 248 249
};


template <typename T,
250
          typename CreateTrait = DefaultCreateTrait<T>,
251
          typename InitOnceTrait = SingleThreadInitOnceTrait,
252 253
          typename DestroyTrait = LeakyInstanceTrait<T> >
struct LazyDynamicInstance {
254 255
  typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
      CreateTrait, InitOnceTrait, DestroyTrait> type;
256 257 258 259 260
};

} }  // namespace v8::internal

#endif  // V8_LAZY_INSTANCE_H_