1*635a8641SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker 5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_NO_DESTRUCTOR_H_ 6*635a8641SAndroid Build Coastguard Worker #define BASE_NO_DESTRUCTOR_H_ 7*635a8641SAndroid Build Coastguard Worker 8*635a8641SAndroid Build Coastguard Worker #include <new> 9*635a8641SAndroid Build Coastguard Worker #include <utility> 10*635a8641SAndroid Build Coastguard Worker 11*635a8641SAndroid Build Coastguard Worker namespace base { 12*635a8641SAndroid Build Coastguard Worker 13*635a8641SAndroid Build Coastguard Worker // A wrapper that makes it easy to create an object of type T with static 14*635a8641SAndroid Build Coastguard Worker // storage duration that: 15*635a8641SAndroid Build Coastguard Worker // - is only constructed on first access 16*635a8641SAndroid Build Coastguard Worker // - never invokes the destructor 17*635a8641SAndroid Build Coastguard Worker // in order to satisfy the styleguide ban on global constructors and 18*635a8641SAndroid Build Coastguard Worker // destructors. 19*635a8641SAndroid Build Coastguard Worker // 20*635a8641SAndroid Build Coastguard Worker // Runtime constant example: 21*635a8641SAndroid Build Coastguard Worker // const std::string& GetLineSeparator() { 22*635a8641SAndroid Build Coastguard Worker // // Forwards to std::string(size_t, char, const Allocator&) constructor. 23*635a8641SAndroid Build Coastguard Worker // static const base::NoDestructor<std::string> s(5, '-'); 24*635a8641SAndroid Build Coastguard Worker // return *s; 25*635a8641SAndroid Build Coastguard Worker // } 26*635a8641SAndroid Build Coastguard Worker // 27*635a8641SAndroid Build Coastguard Worker // More complex initialization with a lambda: 28*635a8641SAndroid Build Coastguard Worker // const std::string& GetSessionNonce() { 29*635a8641SAndroid Build Coastguard Worker // static const base::NoDestructor<std::string> nonce([] { 30*635a8641SAndroid Build Coastguard Worker // std::string s(16); 31*635a8641SAndroid Build Coastguard Worker // crypto::RandString(s.data(), s.size()); 32*635a8641SAndroid Build Coastguard Worker // return s; 33*635a8641SAndroid Build Coastguard Worker // }()); 34*635a8641SAndroid Build Coastguard Worker // return *nonce; 35*635a8641SAndroid Build Coastguard Worker // } 36*635a8641SAndroid Build Coastguard Worker // 37*635a8641SAndroid Build Coastguard Worker // NoDestructor<T> stores the object inline, so it also avoids a pointer 38*635a8641SAndroid Build Coastguard Worker // indirection and a malloc. Also note that since C++11 static local variable 39*635a8641SAndroid Build Coastguard Worker // initialization is thread-safe and so is this pattern. Code should prefer to 40*635a8641SAndroid Build Coastguard Worker // use NoDestructor<T> over: 41*635a8641SAndroid Build Coastguard Worker // - The CR_DEFINE_STATIC_LOCAL() helper macro. 42*635a8641SAndroid Build Coastguard Worker // - A function scoped static T* or T& that is dynamically initialized. 43*635a8641SAndroid Build Coastguard Worker // - A global base::LazyInstance<T>. 44*635a8641SAndroid Build Coastguard Worker // 45*635a8641SAndroid Build Coastguard Worker // Note that since the destructor is never run, this *will* leak memory if used 46*635a8641SAndroid Build Coastguard Worker // as a stack or member variable. Furthermore, a NoDestructor<T> should never 47*635a8641SAndroid Build Coastguard Worker // have global scope as that may require a static initializer. 48*635a8641SAndroid Build Coastguard Worker template <typename T> 49*635a8641SAndroid Build Coastguard Worker class NoDestructor { 50*635a8641SAndroid Build Coastguard Worker public: 51*635a8641SAndroid Build Coastguard Worker // Not constexpr; just write static constexpr T x = ...; if the value should 52*635a8641SAndroid Build Coastguard Worker // be a constexpr. 53*635a8641SAndroid Build Coastguard Worker template <typename... Args> NoDestructor(Args &&...args)54*635a8641SAndroid Build Coastguard Worker explicit NoDestructor(Args&&... args) { 55*635a8641SAndroid Build Coastguard Worker new (storage_) T(std::forward<Args>(args)...); 56*635a8641SAndroid Build Coastguard Worker } 57*635a8641SAndroid Build Coastguard Worker 58*635a8641SAndroid Build Coastguard Worker // Allows copy and move construction of the contained type, to allow 59*635a8641SAndroid Build Coastguard Worker // construction from an initializer list, e.g. for std::vector. NoDestructor(const T & x)60*635a8641SAndroid Build Coastguard Worker explicit NoDestructor(const T& x) { new (storage_) T(x); } NoDestructor(T && x)61*635a8641SAndroid Build Coastguard Worker explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); } 62*635a8641SAndroid Build Coastguard Worker 63*635a8641SAndroid Build Coastguard Worker NoDestructor(const NoDestructor&) = delete; 64*635a8641SAndroid Build Coastguard Worker NoDestructor& operator=(const NoDestructor&) = delete; 65*635a8641SAndroid Build Coastguard Worker 66*635a8641SAndroid Build Coastguard Worker ~NoDestructor() = default; 67*635a8641SAndroid Build Coastguard Worker 68*635a8641SAndroid Build Coastguard Worker const T& operator*() const { return *get(); } 69*635a8641SAndroid Build Coastguard Worker T& operator*() { return *get(); } 70*635a8641SAndroid Build Coastguard Worker 71*635a8641SAndroid Build Coastguard Worker const T* operator->() const { return get(); } 72*635a8641SAndroid Build Coastguard Worker T* operator->() { return get(); } 73*635a8641SAndroid Build Coastguard Worker get()74*635a8641SAndroid Build Coastguard Worker const T* get() const { return reinterpret_cast<const T*>(storage_); } get()75*635a8641SAndroid Build Coastguard Worker T* get() { return reinterpret_cast<T*>(storage_); } 76*635a8641SAndroid Build Coastguard Worker 77*635a8641SAndroid Build Coastguard Worker private: 78*635a8641SAndroid Build Coastguard Worker alignas(T) char storage_[sizeof(T)]; 79*635a8641SAndroid Build Coastguard Worker 80*635a8641SAndroid Build Coastguard Worker #if defined(LEAK_SANITIZER) 81*635a8641SAndroid Build Coastguard Worker // TODO(https://crbug.com/812277): This is a hack to work around the fact 82*635a8641SAndroid Build Coastguard Worker // that LSan doesn't seem to treat NoDestructor as a root for reachability 83*635a8641SAndroid Build Coastguard Worker // analysis. This means that code like this: 84*635a8641SAndroid Build Coastguard Worker // static base::NoDestructor<std::vector<int>> v({1, 2, 3}); 85*635a8641SAndroid Build Coastguard Worker // is considered a leak. Using the standard leak sanitizer annotations to 86*635a8641SAndroid Build Coastguard Worker // suppress leaks doesn't work: std::vector is implicitly constructed before 87*635a8641SAndroid Build Coastguard Worker // calling the base::NoDestructor constructor. 88*635a8641SAndroid Build Coastguard Worker // 89*635a8641SAndroid Build Coastguard Worker // Unfortunately, I haven't been able to demonstrate this issue in simpler 90*635a8641SAndroid Build Coastguard Worker // reproductions: until that's resolved, hold an explicit pointer to the 91*635a8641SAndroid Build Coastguard Worker // placement-new'd object in leak sanitizer mode to help LSan realize that 92*635a8641SAndroid Build Coastguard Worker // objects allocated by the contained type are still reachable. 93*635a8641SAndroid Build Coastguard Worker T* storage_ptr_ = reinterpret_cast<T*>(storage_); 94*635a8641SAndroid Build Coastguard Worker #endif // defined(LEAK_SANITIZER) 95*635a8641SAndroid Build Coastguard Worker }; 96*635a8641SAndroid Build Coastguard Worker 97*635a8641SAndroid Build Coastguard Worker } // namespace base 98*635a8641SAndroid Build Coastguard Worker 99*635a8641SAndroid Build Coastguard Worker #endif // BASE_NO_DESTRUCTOR_H_ 100