Home | History | Annotate | Download | only in wtf
      1 /*
      2  *  Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  *  This library is free software; you can redistribute it and/or
      5  *  modify it under the terms of the GNU Library General Public
      6  *  License as published by the Free Software Foundation; either
      7  *  version 2 of the License, or (at your option) any later version.
      8  *
      9  *  This library is distributed in the hope that it will be useful,
     10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  *  Library General Public License for more details.
     13  *
     14  *  You should have received a copy of the GNU Library General Public License
     15  *  along with this library; see the file COPYING.LIB.  If not, write to
     16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  *  Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef WTF_PassRefPtr_h
     22 #define WTF_PassRefPtr_h
     23 
     24 #include "AlwaysInline.h"
     25 #include "NullPtr.h"
     26 
     27 namespace WTF {
     28 
     29     template<typename T> class RefPtr;
     30     template<typename T> class PassRefPtr;
     31     template<typename T> PassRefPtr<T> adoptRef(T*);
     32 
     33     inline void adopted(const void*) { }
     34 
     35 #if !COMPILER(WINSCW)
     36 #if !PLATFORM(QT)
     37     #define REF_DEREF_INLINE ALWAYS_INLINE
     38 #else
     39     // Using ALWAYS_INLINE broke the Qt build. This may be a GCC bug.
     40     // See https://bugs.webkit.org/show_bug.cgi?id=37253 for details.
     41     #define REF_DEREF_INLINE inline
     42 #endif
     43 #else
     44     // No inlining for WINSCW compiler to prevent the compiler agressively resolving
     45     // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as
     46     // a class member or function arguments before T is defined.
     47     #define REF_DEREF_INLINE
     48 #endif
     49 
     50     template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
     51     {
     52         if (LIKELY(ptr != 0))
     53             ptr->ref();
     54     }
     55 
     56     template<typename T> REF_DEREF_INLINE void derefIfNotNull(T* ptr)
     57     {
     58         if (LIKELY(ptr != 0))
     59             ptr->deref();
     60     }
     61 
     62     #undef REF_DEREF_INLINE
     63 
     64     template<typename T> class PassRefPtr {
     65     public:
     66         PassRefPtr() : m_ptr(0) { }
     67         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
     68         // It somewhat breaks the type system to allow transfer of ownership out of
     69         // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
     70         // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
     71         PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
     72         template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }
     73 
     74         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
     75 
     76         template<typename U> PassRefPtr(const RefPtr<U>&);
     77 
     78         T* get() const { return m_ptr; }
     79 
     80         void clear();
     81         T* leakRef() const WARN_UNUSED_RETURN;
     82 
     83         T& operator*() const { return *m_ptr; }
     84         T* operator->() const { return m_ptr; }
     85 
     86         bool operator!() const { return !m_ptr; }
     87 
     88         // This conversion operator allows implicit conversion to bool but not to other integer types.
     89         typedef T* (PassRefPtr::*UnspecifiedBoolType);
     90         operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
     91 
     92         PassRefPtr& operator=(T*);
     93         PassRefPtr& operator=(const PassRefPtr&);
     94 #if !HAVE(NULLPTR)
     95         PassRefPtr& operator=(std::nullptr_t) { clear(); return *this; }
     96 #endif
     97         template<typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
     98         template<typename U> PassRefPtr& operator=(const RefPtr<U>&);
     99 
    100         friend PassRefPtr adoptRef<T>(T*);
    101 
    102         // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
    103         T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
    104 
    105     private:
    106         // adopting constructor
    107         PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
    108 
    109         mutable T* m_ptr;
    110     };
    111 
    112     // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
    113     // begins life non-null, and can only become null through a call to leakRef()
    114     // or clear().
    115 
    116     // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
    117     // if we use inheritance, GCC's optimizer fails to realize that destruction
    118     // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
    119     // most important code from PassRefPtr.
    120     template<typename T> class NonNullPassRefPtr {
    121     public:
    122         NonNullPassRefPtr(T* ptr)
    123             : m_ptr(ptr)
    124         {
    125             ASSERT(m_ptr);
    126             m_ptr->ref();
    127         }
    128 
    129         template<typename U> NonNullPassRefPtr(const RefPtr<U>& o)
    130             : m_ptr(o.get())
    131         {
    132             ASSERT(m_ptr);
    133             m_ptr->ref();
    134         }
    135 
    136         NonNullPassRefPtr(const NonNullPassRefPtr& o)
    137             : m_ptr(o.leakRef())
    138         {
    139             ASSERT(m_ptr);
    140         }
    141 
    142         template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
    143             : m_ptr(o.leakRef())
    144         {
    145             ASSERT(m_ptr);
    146         }
    147 
    148         template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
    149             : m_ptr(o.leakRef())
    150         {
    151             ASSERT(m_ptr);
    152         }
    153 
    154         ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
    155 
    156         T* get() const { return m_ptr; }
    157 
    158         void clear();
    159         T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; }
    160 
    161         T& operator*() const { return *m_ptr; }
    162         T* operator->() const { return m_ptr; }
    163 
    164         // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
    165         T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
    166 
    167     private:
    168         mutable T* m_ptr;
    169     };
    170 
    171     template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o)
    172         : m_ptr(o.get())
    173     {
    174         T* ptr = m_ptr;
    175         refIfNotNull(ptr);
    176     }
    177 
    178     template<typename T> inline void PassRefPtr<T>::clear()
    179     {
    180         T* ptr = m_ptr;
    181         m_ptr = 0;
    182         derefIfNotNull(ptr);
    183     }
    184 
    185     template<typename T> inline T* PassRefPtr<T>::leakRef() const
    186     {
    187         T* ptr = m_ptr;
    188         m_ptr = 0;
    189         return ptr;
    190     }
    191 
    192     template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o)
    193     {
    194         T* optr = o.get();
    195         refIfNotNull(optr);
    196         T* ptr = m_ptr;
    197         m_ptr = optr;
    198         derefIfNotNull(ptr);
    199         return *this;
    200     }
    201 
    202     template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
    203     {
    204         refIfNotNull(optr);
    205         T* ptr = m_ptr;
    206         m_ptr = optr;
    207         derefIfNotNull(ptr);
    208         return *this;
    209     }
    210 
    211     template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
    212     {
    213         T* ptr = m_ptr;
    214         m_ptr = ref.leakRef();
    215         derefIfNotNull(ptr);
    216         return *this;
    217     }
    218 
    219     template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
    220     {
    221         T* ptr = m_ptr;
    222         m_ptr = ref.leakRef();
    223         derefIfNotNull(ptr);
    224         return *this;
    225     }
    226 
    227     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
    228     {
    229         return a.get() == b.get();
    230     }
    231 
    232     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
    233     {
    234         return a.get() == b.get();
    235     }
    236 
    237     template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
    238     {
    239         return a.get() == b.get();
    240     }
    241 
    242     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
    243     {
    244         return a.get() == b;
    245     }
    246 
    247     template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
    248     {
    249         return a == b.get();
    250     }
    251 
    252     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
    253     {
    254         return a.get() != b.get();
    255     }
    256 
    257     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
    258     {
    259         return a.get() != b.get();
    260     }
    261 
    262     template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
    263     {
    264         return a.get() != b.get();
    265     }
    266 
    267     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
    268     {
    269         return a.get() != b;
    270     }
    271 
    272     template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
    273     {
    274         return a != b.get();
    275     }
    276 
    277     template<typename T> inline PassRefPtr<T> adoptRef(T* p)
    278     {
    279         adopted(p);
    280         return PassRefPtr<T>(p, true);
    281     }
    282 
    283     template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
    284     {
    285         return adoptRef(static_cast<T*>(p.leakRef()));
    286     }
    287 
    288     template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p)
    289     {
    290         return adoptRef(const_cast<T*>(p.leakRef()));
    291     }
    292 
    293     template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
    294     {
    295         return p.get();
    296     }
    297 
    298     template<typename T> inline void NonNullPassRefPtr<T>::clear()
    299     {
    300         T* ptr = m_ptr;
    301         m_ptr = 0;
    302         derefIfNotNull(ptr);
    303     }
    304 
    305 } // namespace WTF
    306 
    307 using WTF::PassRefPtr;
    308 using WTF::NonNullPassRefPtr;
    309 using WTF::adoptRef;
    310 using WTF::static_pointer_cast;
    311 using WTF::const_pointer_cast;
    312 
    313 #endif // WTF_PassRefPtr_h
    314