1From c334673e96ce73cbf1a693c7c85b1450fcd3571c Mon Sep 17 00:00:00 2001 2From: Ben Chan <benchan@chromium.org> 3Date: Fri, 2 Nov 2018 23:07:01 -0700 4Subject: [PATCH] libchrome: add base::NoDestructor<T> 5 6CL:869351 introduces base::NoDestructor<T>, which is preferred in new 7code as a drop-in replacement for a function scoped static T* or T& that 8is dynamically initialized, and a global base::LazyInstance<T>. 9 10This CL patches libchrome to pull in base/no_destructor.h at r599267, so 11that we can migrate existing Chrome OS code to use base::NoDestructor<T> 12before the next libchrome uprev. 13 14BUG=None 15TEST=`emerge-$BOARD librchrome` 16 17Change-Id: I791a70e10da6318ea81eaaec869ba4702361289e 18--- 19 base/no_destructor.h | 98 ++++++++++++++++++++++++++++++++++++++++++++ 20 1 file changed, 98 insertions(+) 21 create mode 100644 base/no_destructor.h 22 23diff --git base/no_destructor.h base/no_destructor.h 24new file mode 100644 25index 0000000..21cfef8 26--- /dev/null 27+++ base/no_destructor.h 28@@ -0,0 +1,98 @@ 29+// Copyright 2018 The Chromium Authors. All rights reserved. 30+// Use of this source code is governed by a BSD-style license that can be 31+// found in the LICENSE file. 32+ 33+#ifndef BASE_NO_DESTRUCTOR_H_ 34+#define BASE_NO_DESTRUCTOR_H_ 35+ 36+#include <new> 37+#include <utility> 38+ 39+namespace base { 40+ 41+// A wrapper that makes it easy to create an object of type T with static 42+// storage duration that: 43+// - is only constructed on first access 44+// - never invokes the destructor 45+// in order to satisfy the styleguide ban on global constructors and 46+// destructors. 47+// 48+// Runtime constant example: 49+// const std::string& GetLineSeparator() { 50+// // Forwards to std::string(size_t, char, const Allocator&) constructor. 51+// static const base::NoDestructor<std::string> s(5, '-'); 52+// return *s; 53+// } 54+// 55+// More complex initialization with a lambda: 56+// const std::string& GetSessionNonce() { 57+// static const base::NoDestructor<std::string> nonce([] { 58+// std::string s(16); 59+// crypto::RandString(s.data(), s.size()); 60+// return s; 61+// }()); 62+// return *nonce; 63+// } 64+// 65+// NoDestructor<T> stores the object inline, so it also avoids a pointer 66+// indirection and a malloc. Also note that since C++11 static local variable 67+// initialization is thread-safe and so is this pattern. Code should prefer to 68+// use NoDestructor<T> over: 69+// - A function scoped static T* or T& that is dynamically initialized. 70+// - A global base::LazyInstance<T>. 71+// 72+// Note that since the destructor is never run, this *will* leak memory if used 73+// as a stack or member variable. Furthermore, a NoDestructor<T> should never 74+// have global scope as that may require a static initializer. 75+template <typename T> 76+class NoDestructor { 77+ public: 78+ // Not constexpr; just write static constexpr T x = ...; if the value should 79+ // be a constexpr. 80+ template <typename... Args> 81+ explicit NoDestructor(Args&&... args) { 82+ new (storage_) T(std::forward<Args>(args)...); 83+ } 84+ 85+ // Allows copy and move construction of the contained type, to allow 86+ // construction from an initializer list, e.g. for std::vector. 87+ explicit NoDestructor(const T& x) { new (storage_) T(x); } 88+ explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); } 89+ 90+ NoDestructor(const NoDestructor&) = delete; 91+ NoDestructor& operator=(const NoDestructor&) = delete; 92+ 93+ ~NoDestructor() = default; 94+ 95+ const T& operator*() const { return *get(); } 96+ T& operator*() { return *get(); } 97+ 98+ const T* operator->() const { return get(); } 99+ T* operator->() { return get(); } 100+ 101+ const T* get() const { return reinterpret_cast<const T*>(storage_); } 102+ T* get() { return reinterpret_cast<T*>(storage_); } 103+ 104+ private: 105+ alignas(T) char storage_[sizeof(T)]; 106+ 107+#if defined(LEAK_SANITIZER) 108+ // TODO(https://crbug.com/812277): This is a hack to work around the fact 109+ // that LSan doesn't seem to treat NoDestructor as a root for reachability 110+ // analysis. This means that code like this: 111+ // static base::NoDestructor<std::vector<int>> v({1, 2, 3}); 112+ // is considered a leak. Using the standard leak sanitizer annotations to 113+ // suppress leaks doesn't work: std::vector is implicitly constructed before 114+ // calling the base::NoDestructor constructor. 115+ // 116+ // Unfortunately, I haven't been able to demonstrate this issue in simpler 117+ // reproductions: until that's resolved, hold an explicit pointer to the 118+ // placement-new'd object in leak sanitizer mode to help LSan realize that 119+ // objects allocated by the contained type are still reachable. 120+ T* storage_ptr_ = reinterpret_cast<T*>(storage_); 121+#endif // defined(LEAK_SANITIZER) 122+}; 123+ 124+} // namespace base 125+ 126+#endif // BASE_NO_DESTRUCTOR_H_ 127-- 1282.19.1.930.g4563a0d9d0-goog 129 130