tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

NeverDestroyed.h (2475B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_NeverDestroyed_h
      8 #define mozilla_NeverDestroyed_h
      9 
     10 #include <new>
     11 #include <type_traits>
     12 #include <utility>
     13 #include "mozilla/Attributes.h"
     14 
     15 namespace mozilla {
     16 
     17 // Helper type for creating a local static member of type `T` when `T` has a
     18 // non-trivial static destructor. When used for the local static value, this
     19 // type will avoid introducing a static destructor for these types, as they
     20 // will survive until shutdown.
     21 //
     22 // This can be very useful to avoid static destructors, which are heavily
     23 // discouraged. Using this type is unnecessary if `T` already has a trivial
     24 // destructor, and may introduce unnecessary extra overhead.
     25 //
     26 // This type must only be used with static local members within a function,
     27 // which will be enforced by the clang static analysis.
     28 template <typename T>
     29 class MOZ_STATIC_LOCAL_CLASS
     30 MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS NeverDestroyed {
     31 public:
     32  static_assert(
     33      !std::is_trivially_destructible_v<T>,
     34      "NeverDestroyed is unnecessary for trivially destructable types");
     35 
     36  // Allow constructing the inner type.
     37  // This isn't constexpr, as it requires invoking placement-new. See the
     38  // comment on `mStorage`.
     39  template <typename... U>
     40  explicit NeverDestroyed(U&&... aArgs) {
     41    new (mStorage) T(std::forward<U>(aArgs)...);
     42  }
     43 
     44  const T& operator*() const { return *get(); }
     45  T& operator*() { return *get(); }
     46 
     47  const T* operator->() const { return get(); }
     48  T* operator->() { return get(); }
     49 
     50  const T* get() const { return reinterpret_cast<const T*>(mStorage); }
     51  T* get() { return reinterpret_cast<T*>(mStorage); }
     52 
     53  // Block copy & move constructor, as the type is not safe to copy.
     54  NeverDestroyed(const NeverDestroyed&) = delete;
     55  NeverDestroyed& operator=(const NeverDestroyed&) = delete;
     56 
     57 private:
     58  // Correctly aligned storage for the type. We unfortunately can't use a union
     59  // for alignment & constexpr initialization as that would require an explicit
     60  // destructor declaration, making `NeverDestroyed` non-trivially destructable.
     61  alignas(T) char mStorage[sizeof(T)];
     62 };
     63 
     64 };  // namespace mozilla
     65 
     66 #endif  // mozilla_NeverDestroyed_h