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