summaryrefslogtreecommitdiffstats
path: root/mfbt/NeverDestroyed.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /mfbt/NeverDestroyed.h
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mfbt/NeverDestroyed.h')
-rw-r--r--mfbt/NeverDestroyed.h66
1 files changed, 66 insertions, 0 deletions
diff --git a/mfbt/NeverDestroyed.h b/mfbt/NeverDestroyed.h
new file mode 100644
index 0000000000..fe3b366c69
--- /dev/null
+++ b/mfbt/NeverDestroyed.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_NeverDestroyed_h
+#define mozilla_NeverDestroyed_h
+
+#include <new>
+#include <type_traits>
+#include <utility>
+#include "mozilla/Attributes.h"
+
+namespace mozilla {
+
+// Helper type for creating a local static member of type `T` when `T` has a
+// non-trivial static destructor. When used for the local static value, this
+// type will avoid introducing a static destructor for these types, as they
+// will survive until shutdown.
+//
+// This can be very useful to avoid static destructors, which are heavily
+// discouraged. Using this type is unnecessary if `T` already has a trivial
+// destructor, and may introduce unnecessary extra overhead.
+//
+// This type must only be used with static local members within a function,
+// which will be enforced by the clang static analysis.
+template <typename T>
+class MOZ_STATIC_LOCAL_CLASS MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS
+ NeverDestroyed {
+ public:
+ static_assert(
+ !std::is_trivially_destructible_v<T>,
+ "NeverDestroyed is unnecessary for trivially destructable types");
+
+ // Allow constructing the inner type.
+ // This isn't constexpr, as it requires invoking placement-new. See the
+ // comment on `mStorage`.
+ template <typename... U>
+ explicit NeverDestroyed(U&&... aArgs) {
+ new (mStorage) T(std::forward<U>(aArgs)...);
+ }
+
+ const T& operator*() const { return *get(); }
+ T& operator*() { return *get(); }
+
+ const T* operator->() const { return get(); }
+ T* operator->() { return get(); }
+
+ const T* get() const { return reinterpret_cast<T*>(mStorage); }
+ T* get() { return reinterpret_cast<T*>(mStorage); }
+
+ // Block copy & move constructor, as the type is not safe to copy.
+ NeverDestroyed(const NeverDestroyed&) = delete;
+ NeverDestroyed& operator=(const NeverDestroyed&) = delete;
+
+ private:
+ // Correctly aligned storage for the type. We unfortunately can't use a union
+ // for alignment & constexpr initialization as that would require an explicit
+ // destructor declaration, making `NeverDestroyed` non-trivially destructable.
+ alignas(T) char mStorage[sizeof(T)];
+};
+
+}; // namespace mozilla
+
+#endif // mozilla_NeverDestroyed_h