11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// The LazyInstance<Type, Traits> class manages a single instance of Type,
61cb0ef41Sopenharmony_ci// which will be lazily created on the first time it's accessed.  This class is
71cb0ef41Sopenharmony_ci// useful for places you would normally use a function-level static, but you
81cb0ef41Sopenharmony_ci// need to have guaranteed thread-safety.  The Type constructor will only ever
91cb0ef41Sopenharmony_ci// be called once, even if two threads are racing to create the object.  Get()
101cb0ef41Sopenharmony_ci// and Pointer() will always return the same, completely initialized instance.
111cb0ef41Sopenharmony_ci//
121cb0ef41Sopenharmony_ci// LazyInstance is completely thread safe, assuming that you create it safely.
131cb0ef41Sopenharmony_ci// The class was designed to be POD initialized, so it shouldn't require a
141cb0ef41Sopenharmony_ci// static constructor.  It really only makes sense to declare a LazyInstance as
151cb0ef41Sopenharmony_ci// a global variable using the LAZY_INSTANCE_INITIALIZER initializer.
161cb0ef41Sopenharmony_ci//
171cb0ef41Sopenharmony_ci// LazyInstance is similar to Singleton, except it does not have the singleton
181cb0ef41Sopenharmony_ci// property.  You can have multiple LazyInstance's of the same type, and each
191cb0ef41Sopenharmony_ci// will manage a unique instance.  It also preallocates the space for Type, as
201cb0ef41Sopenharmony_ci// to avoid allocating the Type instance on the heap.  This may help with the
211cb0ef41Sopenharmony_ci// performance of creating the instance, and reducing heap fragmentation.  This
221cb0ef41Sopenharmony_ci// requires that Type be a complete type so we can determine the size. See
231cb0ef41Sopenharmony_ci// notes for advanced users below for more explanations.
241cb0ef41Sopenharmony_ci//
251cb0ef41Sopenharmony_ci// Example usage:
261cb0ef41Sopenharmony_ci//   static LazyInstance<MyClass>::type my_instance = LAZY_INSTANCE_INITIALIZER;
271cb0ef41Sopenharmony_ci//   void SomeMethod() {
281cb0ef41Sopenharmony_ci//     my_instance.Get().SomeMethod();  // MyClass::SomeMethod()
291cb0ef41Sopenharmony_ci//
301cb0ef41Sopenharmony_ci//     MyClass* ptr = my_instance.Pointer();
311cb0ef41Sopenharmony_ci//     ptr->DoDoDo();  // MyClass::DoDoDo
321cb0ef41Sopenharmony_ci//   }
331cb0ef41Sopenharmony_ci//
341cb0ef41Sopenharmony_ci// Additionally you can override the way your instance is constructed by
351cb0ef41Sopenharmony_ci// providing your own trait:
361cb0ef41Sopenharmony_ci// Example usage:
371cb0ef41Sopenharmony_ci//   struct MyCreateTrait {
381cb0ef41Sopenharmony_ci//     static void Construct(void* allocated_ptr) {
391cb0ef41Sopenharmony_ci//       new (allocated_ptr) MyClass(/* extra parameters... */);
401cb0ef41Sopenharmony_ci//     }
411cb0ef41Sopenharmony_ci//   };
421cb0ef41Sopenharmony_ci//   static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
431cb0ef41Sopenharmony_ci//      LAZY_INSTANCE_INITIALIZER;
441cb0ef41Sopenharmony_ci//
451cb0ef41Sopenharmony_ci// WARNINGS:
461cb0ef41Sopenharmony_ci// - This implementation of LazyInstance IS THREAD-SAFE by default. See
471cb0ef41Sopenharmony_ci//   SingleThreadInitOnceTrait if you don't care about thread safety.
481cb0ef41Sopenharmony_ci// - Lazy initialization comes with a cost. Make sure that you don't use it on
491cb0ef41Sopenharmony_ci//   critical path. Consider adding your initialization code to a function
501cb0ef41Sopenharmony_ci//   which is explicitly called once.
511cb0ef41Sopenharmony_ci//
521cb0ef41Sopenharmony_ci// Notes for advanced users:
531cb0ef41Sopenharmony_ci// LazyInstance can actually be used in two different ways:
541cb0ef41Sopenharmony_ci//
551cb0ef41Sopenharmony_ci// - "Static mode" which is the default mode since it is the most efficient
561cb0ef41Sopenharmony_ci//   (no extra heap allocation). In this mode, the instance is statically
571cb0ef41Sopenharmony_ci//   allocated (stored in the global data section at compile time).
581cb0ef41Sopenharmony_ci//   The macro LAZY_STATIC_INSTANCE_INITIALIZER (= LAZY_INSTANCE_INITIALIZER)
591cb0ef41Sopenharmony_ci//   must be used to initialize static lazy instances.
601cb0ef41Sopenharmony_ci//
611cb0ef41Sopenharmony_ci// - "Dynamic mode". In this mode, the instance is dynamically allocated and
621cb0ef41Sopenharmony_ci//   constructed (using new) by default. This mode is useful if you have to
631cb0ef41Sopenharmony_ci//   deal with some code already allocating the instance for you (e.g.
641cb0ef41Sopenharmony_ci//   OS::Mutex() which returns a new private OS-dependent subclass of Mutex).
651cb0ef41Sopenharmony_ci//   The macro LAZY_DYNAMIC_INSTANCE_INITIALIZER must be used to initialize
661cb0ef41Sopenharmony_ci//   dynamic lazy instances.
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci#ifndef V8_BASE_LAZY_INSTANCE_H_
691cb0ef41Sopenharmony_ci#define V8_BASE_LAZY_INSTANCE_H_
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci#include <type_traits>
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci#include "src/base/macros.h"
741cb0ef41Sopenharmony_ci#include "src/base/once.h"
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_cinamespace v8 {
771cb0ef41Sopenharmony_cinamespace base {
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, { {} } }
801cb0ef41Sopenharmony_ci#define LAZY_DYNAMIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, 0 }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci// Default to static mode.
831cb0ef41Sopenharmony_ci#define LAZY_INSTANCE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_citemplate <typename T>
871cb0ef41Sopenharmony_cistruct LeakyInstanceTrait {
881cb0ef41Sopenharmony_ci  static void Destroy(T* /* instance */) {}
891cb0ef41Sopenharmony_ci};
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci// Traits that define how an instance is allocated and accessed.
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_citemplate <typename T>
961cb0ef41Sopenharmony_cistruct StaticallyAllocatedInstanceTrait {
971cb0ef41Sopenharmony_ci  using StorageType =
981cb0ef41Sopenharmony_ci      typename std::aligned_storage<sizeof(T), alignof(T)>::type;
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  static T* MutableInstance(StorageType* storage) {
1011cb0ef41Sopenharmony_ci    return reinterpret_cast<T*>(storage);
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  template <typename ConstructTrait>
1051cb0ef41Sopenharmony_ci  static void InitStorageUsingTrait(StorageType* storage) {
1061cb0ef41Sopenharmony_ci    ConstructTrait::Construct(storage);
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci};
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_citemplate <typename T>
1121cb0ef41Sopenharmony_cistruct DynamicallyAllocatedInstanceTrait {
1131cb0ef41Sopenharmony_ci  using StorageType = T*;
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  static T* MutableInstance(StorageType* storage) {
1161cb0ef41Sopenharmony_ci    return *storage;
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  template <typename CreateTrait>
1201cb0ef41Sopenharmony_ci  static void InitStorageUsingTrait(StorageType* storage) {
1211cb0ef41Sopenharmony_ci    *storage = CreateTrait::Create();
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci};
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_citemplate <typename T>
1271cb0ef41Sopenharmony_cistruct DefaultConstructTrait {
1281cb0ef41Sopenharmony_ci  // Constructs the provided object which was already allocated.
1291cb0ef41Sopenharmony_ci  static void Construct(void* allocated_ptr) { new (allocated_ptr) T(); }
1301cb0ef41Sopenharmony_ci};
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_citemplate <typename T>
1341cb0ef41Sopenharmony_cistruct DefaultCreateTrait {
1351cb0ef41Sopenharmony_ci  static T* Create() {
1361cb0ef41Sopenharmony_ci    return new T();
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci};
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_cistruct ThreadSafeInitOnceTrait {
1421cb0ef41Sopenharmony_ci  template <typename Function, typename Storage>
1431cb0ef41Sopenharmony_ci  static void Init(OnceType* once, Function function, Storage storage) {
1441cb0ef41Sopenharmony_ci    CallOnce(once, function, storage);
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci};
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci// Initialization trait for users who don't care about thread-safety.
1501cb0ef41Sopenharmony_cistruct SingleThreadInitOnceTrait {
1511cb0ef41Sopenharmony_ci  template <typename Function, typename Storage>
1521cb0ef41Sopenharmony_ci  static void Init(OnceType* once, Function function, Storage storage) {
1531cb0ef41Sopenharmony_ci    if (*once == ONCE_STATE_UNINITIALIZED) {
1541cb0ef41Sopenharmony_ci      function(storage);
1551cb0ef41Sopenharmony_ci      *once = ONCE_STATE_DONE;
1561cb0ef41Sopenharmony_ci    }
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci};
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci// TODO(pliard): Handle instances destruction (using global destructors).
1621cb0ef41Sopenharmony_citemplate <typename T, typename AllocationTrait, typename CreateTrait,
1631cb0ef41Sopenharmony_ci          typename InitOnceTrait, typename DestroyTrait  /* not used yet. */>
1641cb0ef41Sopenharmony_cistruct LazyInstanceImpl {
1651cb0ef41Sopenharmony_ci public:
1661cb0ef41Sopenharmony_ci  using StorageType = typename AllocationTrait::StorageType;
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci private:
1691cb0ef41Sopenharmony_ci  static void InitInstance(void* storage) {
1701cb0ef41Sopenharmony_ci    AllocationTrait::template InitStorageUsingTrait<CreateTrait>(
1711cb0ef41Sopenharmony_ci        static_cast<StorageType*>(storage));
1721cb0ef41Sopenharmony_ci  }
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci  void Init() const {
1751cb0ef41Sopenharmony_ci    InitOnceTrait::Init(&once_, &InitInstance, static_cast<void*>(&storage_));
1761cb0ef41Sopenharmony_ci  }
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci public:
1791cb0ef41Sopenharmony_ci  T* Pointer() {
1801cb0ef41Sopenharmony_ci    Init();
1811cb0ef41Sopenharmony_ci    return AllocationTrait::MutableInstance(&storage_);
1821cb0ef41Sopenharmony_ci  }
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  const T& Get() const {
1851cb0ef41Sopenharmony_ci    Init();
1861cb0ef41Sopenharmony_ci    return *AllocationTrait::MutableInstance(&storage_);
1871cb0ef41Sopenharmony_ci  }
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci  mutable OnceType once_;
1901cb0ef41Sopenharmony_ci  // Note that the previous field, OnceType, is an AtomicWord which guarantees
1911cb0ef41Sopenharmony_ci  // 4-byte alignment of the storage field below. If compiling with GCC (>4.2),
1921cb0ef41Sopenharmony_ci  // the LAZY_ALIGN macro above will guarantee correctness for any alignment.
1931cb0ef41Sopenharmony_ci  mutable StorageType storage_;
1941cb0ef41Sopenharmony_ci};
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_citemplate <typename T,
1981cb0ef41Sopenharmony_ci          typename CreateTrait = DefaultConstructTrait<T>,
1991cb0ef41Sopenharmony_ci          typename InitOnceTrait = ThreadSafeInitOnceTrait,
2001cb0ef41Sopenharmony_ci          typename DestroyTrait = LeakyInstanceTrait<T> >
2011cb0ef41Sopenharmony_cistruct LazyStaticInstance {
2021cb0ef41Sopenharmony_ci  using type = LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
2031cb0ef41Sopenharmony_ci                                CreateTrait, InitOnceTrait, DestroyTrait>;
2041cb0ef41Sopenharmony_ci};
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_citemplate <typename T,
2081cb0ef41Sopenharmony_ci          typename CreateTrait = DefaultConstructTrait<T>,
2091cb0ef41Sopenharmony_ci          typename InitOnceTrait = ThreadSafeInitOnceTrait,
2101cb0ef41Sopenharmony_ci          typename DestroyTrait = LeakyInstanceTrait<T> >
2111cb0ef41Sopenharmony_cistruct LazyInstance {
2121cb0ef41Sopenharmony_ci  // A LazyInstance is a LazyStaticInstance.
2131cb0ef41Sopenharmony_ci  using type = typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
2141cb0ef41Sopenharmony_ci                                           DestroyTrait>::type;
2151cb0ef41Sopenharmony_ci};
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_citemplate <typename T,
2191cb0ef41Sopenharmony_ci          typename CreateTrait = DefaultCreateTrait<T>,
2201cb0ef41Sopenharmony_ci          typename InitOnceTrait = ThreadSafeInitOnceTrait,
2211cb0ef41Sopenharmony_ci          typename DestroyTrait = LeakyInstanceTrait<T> >
2221cb0ef41Sopenharmony_cistruct LazyDynamicInstance {
2231cb0ef41Sopenharmony_ci  using type = LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
2241cb0ef41Sopenharmony_ci                                CreateTrait, InitOnceTrait, DestroyTrait>;
2251cb0ef41Sopenharmony_ci};
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci// LeakyObject<T> wraps an object of type T, which is initialized in the
2281cb0ef41Sopenharmony_ci// constructor but never destructed. Thus LeakyObject<T> is trivially
2291cb0ef41Sopenharmony_ci// destructible and can be used in static (lazily initialized) variables.
2301cb0ef41Sopenharmony_citemplate <typename T>
2311cb0ef41Sopenharmony_ciclass LeakyObject {
2321cb0ef41Sopenharmony_ci public:
2331cb0ef41Sopenharmony_ci  template <typename... Args>
2341cb0ef41Sopenharmony_ci  explicit LeakyObject(Args&&... args) {
2351cb0ef41Sopenharmony_ci    new (&storage_) T(std::forward<Args>(args)...);
2361cb0ef41Sopenharmony_ci  }
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  LeakyObject(const LeakyObject&) = delete;
2391cb0ef41Sopenharmony_ci  LeakyObject& operator=(const LeakyObject&) = delete;
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  T* get() { return reinterpret_cast<T*>(&storage_); }
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci private:
2441cb0ef41Sopenharmony_ci  typename std::aligned_storage<sizeof(T), alignof(T)>::type storage_;
2451cb0ef41Sopenharmony_ci};
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci// Define a function which returns a pointer to a lazily initialized and never
2481cb0ef41Sopenharmony_ci// destructed object of type T.
2491cb0ef41Sopenharmony_ci#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName, ...) \
2501cb0ef41Sopenharmony_ci  T* FunctionName() {                                         \
2511cb0ef41Sopenharmony_ci    static ::v8::base::LeakyObject<T> object{__VA_ARGS__};    \
2521cb0ef41Sopenharmony_ci    return object.get();                                      \
2531cb0ef41Sopenharmony_ci  }
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci}  // namespace base
2561cb0ef41Sopenharmony_ci}  // namespace v8
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci#endif  // V8_BASE_LAZY_INSTANCE_H_
259