File indexing completed on 2024-05-12 15:43:39

0001 /*
0002  *  Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
0003  *
0004  *  This library is free software; you can redistribute it and/or
0005  *  modify it under the terms of the GNU Library General Public
0006  *  License as published by the Free Software Foundation; either
0007  *  version 2 of the License, or (at your option) any later version.
0008  *
0009  *  This library is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  *  Library General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU Library General Public License
0015  *  along with this library; see the file COPYING.LIB.  If not, write to
0016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  *  Boston, MA 02110-1301, USA.
0018  *
0019  */
0020 
0021 #ifndef WTF_PassRefPtr_h
0022 #define WTF_PassRefPtr_h
0023 
0024 #include <wtf/AlwaysInline.h>
0025 
0026 namespace WTF
0027 {
0028 
0029 template<typename T> class RefPtr;
0030 template<typename T> class PassRefPtr;
0031 template <typename T> PassRefPtr<T> adoptRef(T *);
0032 
0033 template<typename T> class PassRefPtr
0034 {
0035 public:
0036     PassRefPtr() : m_ptr(nullptr) {}
0037     PassRefPtr(T *ptr) : m_ptr(ptr)
0038     {
0039         if (ptr) {
0040             ptr->ref();
0041         }
0042     }
0043     // It somewhat breaks the type system to allow transfer of ownership out of
0044     // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
0045     // temporaries, and we don't really have a need to use real const PassRefPtrs
0046     // anyway.
0047     PassRefPtr(const PassRefPtr &o) : m_ptr(o.releaseRef()) {}
0048     template <typename U> PassRefPtr(const PassRefPtr<U> &o) : m_ptr(o.releaseRef()) { }
0049 
0050     ALWAYS_INLINE ~PassRefPtr()
0051     {
0052         if (T *ptr = m_ptr) {
0053             ptr->deref();
0054         }
0055     }
0056 
0057     template <class U>
0058     PassRefPtr(const RefPtr<U> &o) : m_ptr(o.get())
0059     {
0060         if (T *ptr = m_ptr) {
0061             ptr->ref();
0062         }
0063     }
0064 
0065     T *get() const
0066     {
0067         return m_ptr;
0068     }
0069 
0070     void clear()
0071     {
0072         if (T *ptr = m_ptr) {
0073             ptr->deref();
0074         } m_ptr = nullptr;
0075     }
0076     T *releaseRef() const
0077     {
0078         T *tmp = m_ptr;
0079         m_ptr = nullptr;
0080         return tmp;
0081     }
0082 
0083     T &operator*() const
0084     {
0085         return *m_ptr;
0086     }
0087     T *operator->() const
0088     {
0089         return m_ptr;
0090     }
0091 
0092     bool operator!() const
0093     {
0094         return !m_ptr;
0095     }
0096 
0097     // This conversion operator allows implicit conversion to bool but not to other integer types.
0098     typedef T *PassRefPtr::*UnspecifiedBoolType;
0099     operator UnspecifiedBoolType() const
0100     {
0101         return m_ptr ? &PassRefPtr::m_ptr : nullptr;
0102     }
0103 
0104     PassRefPtr &operator=(T *);
0105     PassRefPtr &operator=(const PassRefPtr &);
0106     template <typename U> PassRefPtr &operator=(const PassRefPtr<U> &);
0107     template <typename U> PassRefPtr &operator=(const RefPtr<U> &);
0108 
0109     friend PassRefPtr adoptRef<T>(T *);
0110 private:
0111     // adopting constructor
0112     PassRefPtr(T *ptr, bool) : m_ptr(ptr) {}
0113     mutable T *m_ptr;
0114 };
0115 
0116 template <typename T> template <typename U> inline PassRefPtr<T> &PassRefPtr<T>::operator=(const RefPtr<U> &o)
0117 {
0118     T *optr = o.get();
0119     if (optr) {
0120         optr->ref();
0121     }
0122     T *ptr = m_ptr;
0123     m_ptr = optr;
0124     if (ptr) {
0125         ptr->deref();
0126     }
0127     return *this;
0128 }
0129 
0130 template <typename T> inline PassRefPtr<T> &PassRefPtr<T>::operator=(T *optr)
0131 {
0132     if (optr) {
0133         optr->ref();
0134     }
0135     T *ptr = m_ptr;
0136     m_ptr = optr;
0137     if (ptr) {
0138         ptr->deref();
0139     }
0140     return *this;
0141 }
0142 
0143 template <typename T> inline PassRefPtr<T> &PassRefPtr<T>::operator=(const PassRefPtr<T> &ref)
0144 {
0145     T *ptr = m_ptr;
0146     m_ptr = ref.releaseRef();
0147     if (ptr) {
0148         ptr->deref();
0149     }
0150     return *this;
0151 }
0152 
0153 template <typename T> template <typename U> inline PassRefPtr<T> &PassRefPtr<T>::operator=(const PassRefPtr<U> &ref)
0154 {
0155     T *ptr = m_ptr;
0156     m_ptr = ref.releaseRef();
0157     if (ptr) {
0158         ptr->deref();
0159     }
0160     return *this;
0161 }
0162 
0163 template <typename T, typename U> inline bool operator==(const PassRefPtr<T> &a, const PassRefPtr<U> &b)
0164 {
0165     return a.get() == b.get();
0166 }
0167 
0168 template <typename T, typename U> inline bool operator==(const PassRefPtr<T> &a, const RefPtr<U> &b)
0169 {
0170     return a.get() == b.get();
0171 }
0172 
0173 template <typename T, typename U> inline bool operator==(const RefPtr<T> &a, const PassRefPtr<U> &b)
0174 {
0175     return a.get() == b.get();
0176 }
0177 
0178 template <typename T, typename U> inline bool operator==(const PassRefPtr<T> &a, U *b)
0179 {
0180     return a.get() == b;
0181 }
0182 
0183 template <typename T, typename U> inline bool operator==(T *a, const PassRefPtr<U> &b)
0184 {
0185     return a == b.get();
0186 }
0187 
0188 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T> &a, const PassRefPtr<U> &b)
0189 {
0190     return a.get() != b.get();
0191 }
0192 
0193 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T> &a, const RefPtr<U> &b)
0194 {
0195     return a.get() != b.get();
0196 }
0197 
0198 template <typename T, typename U> inline bool operator!=(const RefPtr<T> &a, const PassRefPtr<U> &b)
0199 {
0200     return a.get() != b.get();
0201 }
0202 
0203 template <typename T, typename U> inline bool operator!=(const PassRefPtr<T> &a, U *b)
0204 {
0205     return a.get() != b;
0206 }
0207 
0208 template <typename T, typename U> inline bool operator!=(T *a, const PassRefPtr<U> &b)
0209 {
0210     return a != b.get();
0211 }
0212 
0213 template <typename T> inline PassRefPtr<T> adoptRef(T *p)
0214 {
0215     return PassRefPtr<T>(p, true);
0216 }
0217 
0218 template <typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U> &p)
0219 {
0220     return adoptRef(static_cast<T *>(p.releaseRef()));
0221 }
0222 
0223 template <typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U> &p)
0224 {
0225     return adoptRef(const_cast<T *>(p.releaseRef()));
0226 }
0227 
0228 template <typename T> inline T *getPtr(const PassRefPtr<T> &p)
0229 {
0230     return p.get();
0231 }
0232 
0233 } // namespace WTF
0234 
0235 using WTF::PassRefPtr;
0236 using WTF::adoptRef;
0237 using WTF::static_pointer_cast;
0238 using WTF::const_pointer_cast;
0239 
0240 #endif // WTF_PassRefPtr_h