13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The LazyInstance<Type, Traits> class manages a single instance of Type,
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// which will be lazily created on the first time it's accessed.  This class is
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// useful for places you would normally use a function-level static, but you
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// need to have guaranteed thread-safety.  The Type constructor will only ever
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// be called once, even if two threads are racing to create the object.  Get()
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and Pointer() will always return the same, completely initialized instance.
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LazyInstance is completely thread safe, assuming that you create it safely.
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The class was designed to be POD initialized, so it shouldn't require a
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// static constructor.  It really only makes sense to declare a LazyInstance as
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// a global variable using the LAZY_INSTANCE_INITIALIZER initializer.
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LazyInstance is similar to Singleton, except it does not have the singleton
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// property.  You can have multiple LazyInstance's of the same type, and each
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// will manage a unique instance.  It also preallocates the space for Type, as
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// to avoid allocating the Type instance on the heap.  This may help with the
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// performance of creating the instance, and reducing heap fragmentation.  This
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// requires that Type be a complete type so we can determine the size. See
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// notes for advanced users below for more explanations.
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Example usage:
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   static LazyInstance<MyClass>::type my_instance = LAZY_INSTANCE_INITIALIZER;
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   void SomeMethod() {
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     my_instance.Get().SomeMethod();  // MyClass::SomeMethod()
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     MyClass* ptr = my_instance.Pointer();
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     ptr->DoDoDo();  // MyClass::DoDoDo
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   }
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Additionally you can override the way your instance is constructed by
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// providing your own trait:
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Example usage:
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   struct MyCreateTrait {
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     static void Construct(MyClass* allocated_ptr) {
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       new (allocated_ptr) MyClass(/* extra parameters... */);
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     }
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   };
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//      LAZY_INSTANCE_INITIALIZER;
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// WARNINGS:
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - This implementation of LazyInstance IS THREAD-SAFE by default. See
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   SingleThreadInitOnceTrait if you don't care about thread safety.
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - Lazy initialization comes with a cost. Make sure that you don't use it on
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   critical path. Consider adding your initialization code to a function
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   which is explicitly called once.
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Notes for advanced users:
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LazyInstance can actually be used in two different ways:
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// - "Static mode" which is the default mode since it is the most efficient
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   (no extra heap allocation). In this mode, the instance is statically
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   allocated (stored in the global data section at compile time).
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   The macro LAZY_STATIC_INSTANCE_INITIALIZER (= LAZY_INSTANCE_INITIALIZER)
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   must be used to initialize static lazy instances.
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// - "Dynamic mode". In this mode, the instance is dynamically allocated and
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   constructed (using new) by default. This mode is useful if you have to
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   deal with some code already allocating the instance for you (e.g.
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   OS::Mutex() which returns a new private OS-dependent subclass of Mutex).
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   The macro LAZY_DYNAMIC_INSTANCE_INITIALIZER must be used to initialize
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   dynamic lazy instances.
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_BASE_LAZY_INSTANCE_H_
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_BASE_LAZY_INSTANCE_H_
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/macros.h"
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/once.h"
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base {
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, { {} } }
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_DYNAMIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, 0 }
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Default to static mode.
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_INSTANCE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LeakyInstanceTrait {
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Destroy(T* /* instance */) {}
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Traits that define how an instance is allocated and accessed.
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct StaticallyAllocatedInstanceTrait {
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 16-byte alignment fallback to be on the safe side here.
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct V8_ALIGNAS(T, 16) StorageType {
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    char x[sizeof(T)];
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(V8_ALIGNOF(StorageType) >= V8_ALIGNOF(T));
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static T* MutableInstance(StorageType* storage) {
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return reinterpret_cast<T*>(storage);
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename ConstructTrait>
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void InitStorageUsingTrait(StorageType* storage) {
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ConstructTrait::Construct(MutableInstance(storage));
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct DynamicallyAllocatedInstanceTrait {
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef T* StorageType;
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static T* MutableInstance(StorageType* storage) {
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return *storage;
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename CreateTrait>
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void InitStorageUsingTrait(StorageType* storage) {
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *storage = CreateTrait::Create();
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct DefaultConstructTrait {
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Constructs the provided object which was already allocated.
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Construct(T* allocated_ptr) {
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new(allocated_ptr) T();
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct DefaultCreateTrait {
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static T* Create() {
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return new T();
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct ThreadSafeInitOnceTrait {
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename Function, typename Storage>
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Init(OnceType* once, Function function, Storage storage) {
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallOnce(once, function, storage);
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Initialization trait for users who don't care about thread-safety.
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct SingleThreadInitOnceTrait {
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename Function, typename Storage>
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Init(OnceType* once, Function function, Storage storage) {
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*once == ONCE_STATE_UNINITIALIZED) {
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function(storage);
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *once = ONCE_STATE_DONE;
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(pliard): Handle instances destruction (using global destructors).
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T, typename AllocationTrait, typename CreateTrait,
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename InitOnceTrait, typename DestroyTrait  /* not used yet. */>
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyInstanceImpl {
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename AllocationTrait::StorageType StorageType;
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void InitInstance(StorageType* storage) {
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AllocationTrait::template InitStorageUsingTrait<CreateTrait>(storage);
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Init() const {
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InitOnceTrait::Init(
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        &once_,
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Casts to void* are needed here to avoid breaking strict aliasing
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // rules.
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reinterpret_cast<void(*)(void*)>(&InitInstance),  // NOLINT
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reinterpret_cast<void*>(&storage_));
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  T* Pointer() {
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Init();
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return AllocationTrait::MutableInstance(&storage_);
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const T& Get() const {
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Init();
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return *AllocationTrait::MutableInstance(&storage_);
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mutable OnceType once_;
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that the previous field, OnceType, is an AtomicWord which guarantees
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 4-byte alignment of the storage field below. If compiling with GCC (>4.2),
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the LAZY_ALIGN macro above will guarantee correctness for any alignment.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mutable StorageType storage_;
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T,
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename CreateTrait = DefaultConstructTrait<T>,
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          typename InitOnceTrait = ThreadSafeInitOnceTrait,
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename DestroyTrait = LeakyInstanceTrait<T> >
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyStaticInstance {
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CreateTrait, InitOnceTrait, DestroyTrait> type;
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T,
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename CreateTrait = DefaultConstructTrait<T>,
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          typename InitOnceTrait = ThreadSafeInitOnceTrait,
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename DestroyTrait = LeakyInstanceTrait<T> >
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyInstance {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A LazyInstance is a LazyStaticInstance.
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DestroyTrait>::type type;
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T,
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          typename CreateTrait = DefaultCreateTrait<T>,
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          typename InitOnceTrait = ThreadSafeInitOnceTrait,
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename DestroyTrait = LeakyInstanceTrait<T> >
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyDynamicInstance {
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CreateTrait, InitOnceTrait, DestroyTrait> type;
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace base
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_BASE_LAZY_INSTANCE_H_
239