From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- xpcom/base/StaticPtr.h | 235 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 xpcom/base/StaticPtr.h (limited to 'xpcom/base/StaticPtr.h') diff --git a/xpcom/base/StaticPtr.h b/xpcom/base/StaticPtr.h new file mode 100644 index 0000000000..38fcd82f97 --- /dev/null +++ b/xpcom/base/StaticPtr.h @@ -0,0 +1,235 @@ +/* -*- 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_StaticPtr_h +#define mozilla_StaticPtr_h + +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" +#include "mozilla/RefPtr.h" + +namespace mozilla { + +/** + * StaticAutoPtr and StaticRefPtr are like UniquePtr and RefPtr, except they + * are suitable for use as global variables. + * + * In particular, a global instance of Static{Auto,Ref}Ptr doesn't cause the + * compiler to emit a static initializer. + * + * Since the compiler guarantees that all global variables are initialized to + * 0, the default constexpr constructors will result in no actual code being + * generated. Since we rely on this, the clang plugin, run as part of our + * "static analysis" builds, makes it a compile-time error to use + * Static{Auto,Ref}Ptr as anything except a global variable. + * + * Static{Auto,Ref}Ptr have a limited interface as compared to ns{Auto,Ref}Ptr; + * this is intentional, since their range of acceptable uses is smaller. + */ + +template +class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticAutoPtr { + public: + constexpr StaticAutoPtr() = default; + StaticAutoPtr(const StaticAutoPtr&) = delete; + + StaticAutoPtr& operator=(T* aRhs) { + Assign(aRhs); + return *this; + } + + T* get() const { return mRawPtr; } + + operator T*() const { return get(); } + + T* operator->() const { + MOZ_ASSERT(mRawPtr); + return get(); + } + + T& operator*() const { return *get(); } + + T* forget() { + T* temp = mRawPtr; + mRawPtr = nullptr; + return temp; + } + + private: + void Assign(T* aNewPtr) { + MOZ_ASSERT(!aNewPtr || mRawPtr != aNewPtr); + T* oldPtr = mRawPtr; + mRawPtr = aNewPtr; + delete oldPtr; + } + + T* mRawPtr = nullptr; +}; + +template +class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticRefPtr { + public: + constexpr StaticRefPtr() = default; + StaticRefPtr(const StaticRefPtr&) = delete; + + StaticRefPtr& operator=(T* aRhs) { + AssignWithAddref(aRhs); + return *this; + } + + StaticRefPtr& operator=(const StaticRefPtr& aRhs) { + return (this = aRhs.mRawPtr); + } + + StaticRefPtr& operator=(already_AddRefed& aRhs) { + AssignAssumingAddRef(aRhs.take()); + return *this; + } + + template + StaticRefPtr& operator=(RefPtr&& aRhs) { + AssignAssumingAddRef(aRhs.forget().take()); + return *this; + } + + StaticRefPtr& operator=(already_AddRefed&& aRhs) { + AssignAssumingAddRef(aRhs.take()); + return *this; + } + + already_AddRefed forget() { + T* temp = mRawPtr; + mRawPtr = nullptr; + return already_AddRefed(temp); + } + + T* get() const { return mRawPtr; } + + operator T*() const { return get(); } + + T* operator->() const { + MOZ_ASSERT(mRawPtr); + return get(); + } + + T& operator*() const { return *get(); } + + private: + void AssignWithAddref(T* aNewPtr) { + if (aNewPtr) { + RefPtrTraits::AddRef(aNewPtr); + } + AssignAssumingAddRef(aNewPtr); + } + + void AssignAssumingAddRef(T* aNewPtr) { + T* oldPtr = mRawPtr; + mRawPtr = aNewPtr; + if (oldPtr) { + RefPtrTraits::Release(oldPtr); + } + } + + T* MOZ_OWNING_REF mRawPtr = nullptr; +}; + +namespace StaticPtr_internal { +class Zero; +} // namespace StaticPtr_internal + +#define REFLEXIVE_EQUALITY_OPERATORS(type1, type2, eq_fn, ...) \ + template <__VA_ARGS__> \ + inline bool operator==(type1 lhs, type2 rhs) { \ + return eq_fn; \ + } \ + \ + template <__VA_ARGS__> \ + inline bool operator==(type2 lhs, type1 rhs) { \ + return rhs == lhs; \ + } \ + \ + template <__VA_ARGS__> \ + inline bool operator!=(type1 lhs, type2 rhs) { \ + return !(lhs == rhs); \ + } \ + \ + template <__VA_ARGS__> \ + inline bool operator!=(type2 lhs, type1 rhs) { \ + return !(lhs == rhs); \ + } + +// StaticAutoPtr (in)equality operators + +template +inline bool operator==(const StaticAutoPtr& aLhs, + const StaticAutoPtr& aRhs) { + return aLhs.get() == aRhs.get(); +} + +template +inline bool operator!=(const StaticAutoPtr& aLhs, + const StaticAutoPtr& aRhs) { + return !(aLhs == aRhs); +} + +REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr&, const U*, + lhs.get() == rhs, class T, class U) + +REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr&, U*, lhs.get() == rhs, + class T, class U) + +// Let us compare StaticAutoPtr to 0. +REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr&, StaticPtr_internal::Zero*, + lhs.get() == nullptr, class T) + +// StaticRefPtr (in)equality operators + +template +inline bool operator==(const StaticRefPtr& aLhs, + const StaticRefPtr& aRhs) { + return aLhs.get() == aRhs.get(); +} + +template +inline bool operator!=(const StaticRefPtr& aLhs, + const StaticRefPtr& aRhs) { + return !(aLhs == aRhs); +} + +REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr&, const U*, lhs.get() == rhs, + class T, class U) + +REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr&, U*, lhs.get() == rhs, + class T, class U) + +// Let us compare StaticRefPtr to 0. +REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr&, StaticPtr_internal::Zero*, + lhs.get() == nullptr, class T) + +#undef REFLEXIVE_EQUALITY_OPERATORS + +} // namespace mozilla + +// Declared in mozilla/RefPtr.h +template +template +RefPtr::RefPtr(const mozilla::StaticRefPtr& aOther) + : RefPtr(aOther.get()) {} + +template +template +RefPtr& RefPtr::operator=(const mozilla::StaticRefPtr& aOther) { + return operator=(aOther.get()); +} + +template +inline already_AddRefed do_AddRef(const mozilla::StaticRefPtr& aObj) { + RefPtr ref(aObj); + return ref.forget(); +} + +#endif -- cgit v1.2.3