/* -*- 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
quality 100%
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland