1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #pragma once
5 #include <utility>
6 namespace android::base {
7 // A wrapper that makes it easy to create an object of type T with static
8 // storage duration that:
9 // - is only constructed on first access
10 // - never invokes the destructor
11 // in order to satisfy the styleguide ban on global constructors and
12 // destructors.
13 //
14 // Runtime constant example:
15 // const std::string& GetLineSeparator() {
16 //  // Forwards to std::string(size_t, char, const Allocator&) constructor.
17 //   static const base::NoDestructor<std::string> s(5, '-');
18 //   return s;
19 // }
20 //
21 // More complex initialization with a lambda:
22 // const std::string& GetSessionNonce() {
23 //   static const base::NoDestructor<std::string> nonce([] {
24 //     std::string s(16);
25 //     crypto::RandString(s.data(), s.size());
26 //     return s;
27 //   })());
28 //   return *nonce;
29 // }
30 //
31 // NoDestructor<T> stores the object inline, so it also avoids a pointer
32 // indirection and a malloc. Code should prefer to use NoDestructor<T> over:
33 // - The CR_DEFINE_STATIC_LOCAL() helper macro.
34 // - A function scoped static T* or T& that is dynamically initialized.
35 // - A global base::LazyInstance<T>.
36 //
37 // Note that since the destructor is never run, this *will* leak memory if used
38 // as a stack or member variable. Furthermore, a NoDestructor<T> should never
39 // have global scope as that may require a static initializer.
40 template <typename T>
41 class NoDestructor {
42    public:
43     // Not constexpr; just write static constexpr T x = ...; if the value should
44     // be a constexpr.
45     template <typename... Args>
NoDestructor(Args &&...args)46     explicit NoDestructor(Args&&... args) {
47         new (get()) T(std::forward<Args>(args)...);
48     }
49     ~NoDestructor() = default;
50     const T& operator*() const { return *get(); }
51     T& operator*() { return *get(); }
52     const T* operator->() const { return get(); }
53     T* operator->() { return get(); }
get()54     const T* get() const { return reinterpret_cast<const T*>(&storage_); }
get()55     T* get() { return reinterpret_cast<T*>(&storage_); }
56 
57    private:
58     alignas(T) char storage_[sizeof(T)];
59 };
60 }  // namespace android::base
61