no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / mfbt / NeverDestroyed.h
blobfe3b366c6946fd949d31754666983582d084d074
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/. */
7 #ifndef mozilla_NeverDestroyed_h
8 #define mozilla_NeverDestroyed_h
10 #include <new>
11 #include <type_traits>
12 #include <utility>
13 #include "mozilla/Attributes.h"
15 namespace mozilla {
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.
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.
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 MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS
30 NeverDestroyed {
31 public:
32 static_assert(
33 !std::is_trivially_destructible_v<T>,
34 "NeverDestroyed is unnecessary for trivially destructable types");
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)...);
44 const T& operator*() const { return *get(); }
45 T& operator*() { return *get(); }
47 const T* operator->() const { return get(); }
48 T* operator->() { return get(); }
50 const T* get() const { return reinterpret_cast<T*>(mStorage); }
51 T* get() { return reinterpret_cast<T*>(mStorage); }
53 // Block copy & move constructor, as the type is not safe to copy.
54 NeverDestroyed(const NeverDestroyed&) = delete;
55 NeverDestroyed& operator=(const NeverDestroyed&) = delete;
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)];
64 }; // namespace mozilla
66 #endif // mozilla_NeverDestroyed_h