mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			235 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- 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 T>
 | 
						|
class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticAutoPtr {
 | 
						|
 public:
 | 
						|
  constexpr StaticAutoPtr() = default;
 | 
						|
  StaticAutoPtr(const StaticAutoPtr&) = delete;
 | 
						|
 | 
						|
  StaticAutoPtr<T>& 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 T>
 | 
						|
class MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS StaticRefPtr {
 | 
						|
 public:
 | 
						|
  constexpr StaticRefPtr() = default;
 | 
						|
  StaticRefPtr(const StaticRefPtr&) = delete;
 | 
						|
 | 
						|
  StaticRefPtr<T>& operator=(T* aRhs) {
 | 
						|
    AssignWithAddref(aRhs);
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  StaticRefPtr<T>& operator=(const StaticRefPtr<T>& aRhs) {
 | 
						|
    return (this = aRhs.mRawPtr);
 | 
						|
  }
 | 
						|
 | 
						|
  StaticRefPtr<T>& operator=(already_AddRefed<T>& aRhs) {
 | 
						|
    AssignAssumingAddRef(aRhs.take());
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  template <typename U>
 | 
						|
  StaticRefPtr<T>& operator=(RefPtr<U>&& aRhs) {
 | 
						|
    AssignAssumingAddRef(aRhs.forget().take());
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  StaticRefPtr<T>& operator=(already_AddRefed<T>&& aRhs) {
 | 
						|
    AssignAssumingAddRef(aRhs.take());
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  already_AddRefed<T> forget() {
 | 
						|
    T* temp = mRawPtr;
 | 
						|
    mRawPtr = nullptr;
 | 
						|
    return already_AddRefed<T>(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<T>::AddRef(aNewPtr);
 | 
						|
    }
 | 
						|
    AssignAssumingAddRef(aNewPtr);
 | 
						|
  }
 | 
						|
 | 
						|
  void AssignAssumingAddRef(T* aNewPtr) {
 | 
						|
    T* oldPtr = mRawPtr;
 | 
						|
    mRawPtr = aNewPtr;
 | 
						|
    if (oldPtr) {
 | 
						|
      RefPtrTraits<T>::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 <class T, class U>
 | 
						|
inline bool operator==(const StaticAutoPtr<T>& aLhs,
 | 
						|
                       const StaticAutoPtr<U>& aRhs) {
 | 
						|
  return aLhs.get() == aRhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template <class T, class U>
 | 
						|
inline bool operator!=(const StaticAutoPtr<T>& aLhs,
 | 
						|
                       const StaticAutoPtr<U>& aRhs) {
 | 
						|
  return !(aLhs == aRhs);
 | 
						|
}
 | 
						|
 | 
						|
REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, const U*,
 | 
						|
                             lhs.get() == rhs, class T, class U)
 | 
						|
 | 
						|
REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, U*, lhs.get() == rhs,
 | 
						|
                             class T, class U)
 | 
						|
 | 
						|
// Let us compare StaticAutoPtr to 0.
 | 
						|
REFLEXIVE_EQUALITY_OPERATORS(const StaticAutoPtr<T>&, StaticPtr_internal::Zero*,
 | 
						|
                             lhs.get() == nullptr, class T)
 | 
						|
 | 
						|
// StaticRefPtr (in)equality operators
 | 
						|
 | 
						|
template <class T, class U>
 | 
						|
inline bool operator==(const StaticRefPtr<T>& aLhs,
 | 
						|
                       const StaticRefPtr<U>& aRhs) {
 | 
						|
  return aLhs.get() == aRhs.get();
 | 
						|
}
 | 
						|
 | 
						|
template <class T, class U>
 | 
						|
inline bool operator!=(const StaticRefPtr<T>& aLhs,
 | 
						|
                       const StaticRefPtr<U>& aRhs) {
 | 
						|
  return !(aLhs == aRhs);
 | 
						|
}
 | 
						|
 | 
						|
REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, const U*, lhs.get() == rhs,
 | 
						|
                             class T, class U)
 | 
						|
 | 
						|
REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, U*, lhs.get() == rhs,
 | 
						|
                             class T, class U)
 | 
						|
 | 
						|
// Let us compare StaticRefPtr to 0.
 | 
						|
REFLEXIVE_EQUALITY_OPERATORS(const StaticRefPtr<T>&, StaticPtr_internal::Zero*,
 | 
						|
                             lhs.get() == nullptr, class T)
 | 
						|
 | 
						|
#undef REFLEXIVE_EQUALITY_OPERATORS
 | 
						|
 | 
						|
}  // namespace mozilla
 | 
						|
 | 
						|
// Declared in mozilla/RefPtr.h
 | 
						|
template <class T>
 | 
						|
template <class U>
 | 
						|
RefPtr<T>::RefPtr(const mozilla::StaticRefPtr<U>& aOther)
 | 
						|
    : RefPtr(aOther.get()) {}
 | 
						|
 | 
						|
template <class T>
 | 
						|
template <class U>
 | 
						|
RefPtr<T>& RefPtr<T>::operator=(const mozilla::StaticRefPtr<U>& aOther) {
 | 
						|
  return operator=(aOther.get());
 | 
						|
}
 | 
						|
 | 
						|
template <class T>
 | 
						|
inline already_AddRefed<T> do_AddRef(const mozilla::StaticRefPtr<T>& aObj) {
 | 
						|
  RefPtr<T> ref(aObj);
 | 
						|
  return ref.forget();
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |