13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Redistribution and use in source and binary forms, with or without
33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// modification, are permitted provided that the following conditions are
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// met:
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions of source code must retain the above copyright
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       notice, this list of conditions and the following disclaimer.
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions in binary form must reproduce the above
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       copyright notice, this list of conditions and the following
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       disclaimer in the documentation and/or other materials provided
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       with the distribution.
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Neither the name of Google Inc. nor the names of its
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       contributors may be used to endorse or promote products derived
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       from this software without specific prior written permission.
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The LazyInstance<Type, Traits> class manages a single instance of Type,
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// which will be lazily created on the first time it's accessed.  This class is
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// useful for places you would normally use a function-level static, but you
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// need to have guaranteed thread-safety.  The Type constructor will only ever
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// be called once, even if two threads are racing to create the object.  Get()
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and Pointer() will always return the same, completely initialized instance.
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LazyInstance is completely thread safe, assuming that you create it safely.
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The class was designed to be POD initialized, so it shouldn't require a
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// static constructor.  It really only makes sense to declare a LazyInstance as
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// a global variable using the LAZY_INSTANCE_INITIALIZER initializer.
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LazyInstance is similar to Singleton, except it does not have the singleton
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// property.  You can have multiple LazyInstance's of the same type, and each
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// will manage a unique instance.  It also preallocates the space for Type, as
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// to avoid allocating the Type instance on the heap.  This may help with the
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// performance of creating the instance, and reducing heap fragmentation.  This
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// requires that Type be a complete type so we can determine the size. See
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// notes for advanced users below for more explanations.
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Example usage:
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   static LazyInstance<MyClass>::type my_instance = LAZY_INSTANCE_INITIALIZER;
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   void SomeMethod() {
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     my_instance.Get().SomeMethod();  // MyClass::SomeMethod()
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     MyClass* ptr = my_instance.Pointer();
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     ptr->DoDoDo();  // MyClass::DoDoDo
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   }
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Additionally you can override the way your instance is constructed by
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// providing your own trait:
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Example usage:
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   struct MyCreateTrait {
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     static void Construct(MyClass* allocated_ptr) {
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       new (allocated_ptr) MyClass(/* extra parameters... */);
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     }
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   };
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//      LAZY_INSTANCE_INITIALIZER;
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// WARNING: This implementation of LazyInstance is NOT thread-safe by default.
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// See ThreadSafeInitOnceTrait declared below for that.
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Notes for advanced users:
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LazyInstance can actually be used in two different ways:
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// - "Static mode" which is the default mode since it is the most efficient
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   (no extra heap allocation). In this mode, the instance is statically
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   allocated (stored in the global data section at compile time).
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   The macro LAZY_STATIC_INSTANCE_INITIALIZER (= LAZY_INSTANCE_INITIALIZER)
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   must be used to initialize static lazy instances.
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// - "Dynamic mode". In this mode, the instance is dynamically allocated and
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   constructed (using new) by default. This mode is useful if you have to
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   deal with some code already allocating the instance for you (e.g.
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   OS::Mutex() which returns a new private OS-dependent subclass of Mutex).
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   The macro LAZY_DYNAMIC_INSTANCE_INITIALIZER must be used to initialize
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   dynamic lazy instances.
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifndef V8_LAZY_INSTANCE_H_
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define V8_LAZY_INSTANCE_H_
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "once.h"
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal {
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, {} }
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_DYNAMIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, 0 }
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Default to static mode.
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_INSTANCE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LeakyInstanceTrait {
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Destroy(T* /* instance */) {}
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Traits that define how an instance is allocated and accessed.
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(kalmard): __alignof__ is only defined for GCC > 4.2. Fix alignment issue
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// on MIPS with other compilers.
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2))
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_ALIGN(x) __attribute__((aligned(__alignof__(x))))
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define LAZY_ALIGN(x)
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct StaticallyAllocatedInstanceTrait {
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef char StorageType[sizeof(T)] LAZY_ALIGN(T);
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static T* MutableInstance(StorageType* storage) {
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return reinterpret_cast<T*>(storage);
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename ConstructTrait>
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void InitStorageUsingTrait(StorageType* storage) {
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ConstructTrait::Construct(MutableInstance(storage));
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef LAZY_ALIGN
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct DynamicallyAllocatedInstanceTrait {
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef T* StorageType;
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static T* MutableInstance(StorageType* storage) {
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return *storage;
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename CreateTrait>
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void InitStorageUsingTrait(StorageType* storage) {
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *storage = CreateTrait::Create();
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct DefaultConstructTrait {
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Constructs the provided object which was already allocated.
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Construct(T* allocated_ptr) {
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    new(allocated_ptr) T();
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T>
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct DefaultCreateTrait {
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static T* Create() {
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return new T();
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct ThreadSafeInitOnceTrait {
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename Function, typename Storage>
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Init(OnceType* once, Function function, Storage storage) {
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CallOnce(once, function, storage);
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Initialization trait for users who don't care about thread-safety.
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct SingleThreadInitOnceTrait {
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  template <typename Function, typename Storage>
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Init(OnceType* once, Function function, Storage storage) {
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*once == ONCE_STATE_UNINITIALIZED) {
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function(storage);
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *once = ONCE_STATE_DONE;
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(pliard): Handle instances destruction (using global destructors).
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T, typename AllocationTrait, typename CreateTrait,
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename InitOnceTrait, typename DestroyTrait  /* not used yet. */>
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyInstanceImpl {
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename AllocationTrait::StorageType StorageType;
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void InitInstance(StorageType* storage) {
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AllocationTrait::template InitStorageUsingTrait<CreateTrait>(storage);
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Init() const {
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InitOnceTrait::Init(
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        &once_,
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Casts to void* are needed here to avoid breaking strict aliasing
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // rules.
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reinterpret_cast<void(*)(void*)>(&InitInstance),  // NOLINT
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reinterpret_cast<void*>(&storage_));
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  T* Pointer() {
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Init();
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return AllocationTrait::MutableInstance(&storage_);
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const T& Get() const {
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Init();
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return *AllocationTrait::MutableInstance(&storage_);
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mutable OnceType once_;
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Note that the previous field, OnceType, is an AtomicWord which guarantees
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 4-byte alignment of the storage field below. If compiling with GCC (>4.2),
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the LAZY_ALIGN macro above will guarantee correctness for any alignment.
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mutable StorageType storage_;
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T,
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename CreateTrait = DefaultConstructTrait<T>,
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename InitOnceTrait = SingleThreadInitOnceTrait,
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename DestroyTrait = LeakyInstanceTrait<T> >
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyStaticInstance {
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CreateTrait, InitOnceTrait, DestroyTrait> type;
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T,
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename CreateTrait = DefaultConstructTrait<T>,
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename InitOnceTrait = SingleThreadInitOnceTrait,
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename DestroyTrait = LeakyInstanceTrait<T> >
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyInstance {
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A LazyInstance is a LazyStaticInstance.
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DestroyTrait>::type type;
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename T,
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename CreateTrait = DefaultConstructTrait<T>,
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename InitOnceTrait = SingleThreadInitOnceTrait,
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename DestroyTrait = LeakyInstanceTrait<T> >
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstruct LazyDynamicInstance {
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CreateTrait, InitOnceTrait, DestroyTrait> type;
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} }  // namespace v8::internal
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif  // V8_LAZY_INSTANCE_H_
260