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