Home | History | Annotate | Download | only in wtf
      1 /*
      2  *  Copyright (C) 2005, 2006, 2007 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 
     26 namespace WTF {
     27 
     28     template<typename T> class RefPtr;
     29     template<typename T> class PassRefPtr;
     30     template <typename T> PassRefPtr<T> adoptRef(T*);
     31 
     32 
     33     // Remove inline for WINSCW compiler to prevent the compiler agressively resolving
     34     // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as
     35     // a class member or function arguments before T is defined.
     36     template<typename T>
     37 #if !COMPILER(WINSCW)
     38     inline
     39 #endif
     40     void refIfNotNull(T* ptr)
     41     {
     42         if (UNLIKELY(ptr != 0))
     43             ptr->ref();
     44     }
     45 
     46     template<typename T>
     47 #if !COMPILER(WINSCW)
     48     inline
     49 #endif
     50     void derefIfNotNull(T* ptr)
     51     {
     52         if (UNLIKELY(ptr != 0))
     53             ptr->deref();
     54     }
     55 
     56     template<typename T> class PassRefPtr {
     57     public:
     58         PassRefPtr() : m_ptr(0) {}
     59         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
     60         // It somewhat breaks the type system to allow transfer of ownership out of
     61         // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
     62         // temporaries, and we don't really have a need to use real const PassRefPtrs
     63         // anyway.
     64         PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {}
     65         template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { }
     66 
     67         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
     68 
     69         template <class U>
     70         PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); }
     71 
     72         T* get() const { return m_ptr; }
     73 
     74         void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; }
     75         T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
     76 
     77         T& operator*() const { return *m_ptr; }
     78         T* operator->() const { return m_ptr; }
     79 
     80         bool operator!() const { return !m_ptr; }
     81 
     82         // This conversion operator allows implicit conversion to bool but not to other integer types.
     83         typedef T* (PassRefPtr::*UnspecifiedBoolType);
     84         operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }
     85 
     86         PassRefPtr& operator=(T*);
     87         PassRefPtr& operator=(const PassRefPtr&);
     88         template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
     89         template <typename U> PassRefPtr& operator=(const RefPtr<U>&);
     90 
     91         friend PassRefPtr adoptRef<T>(T*);
     92     private:
     93         // adopting constructor
     94         PassRefPtr(T* ptr, bool) : m_ptr(ptr) {}
     95         mutable T* m_ptr;
     96     };
     97 
     98     // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
     99     // begins life non-null, and can only become null through a call to releaseRef()
    100     // or clear().
    101 
    102     // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
    103     // if we use inheritance, GCC's optimizer fails to realize that destruction
    104     // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
    105     // most important code from PassRefPtr.
    106     template <typename T> class NonNullPassRefPtr {
    107     public:
    108         NonNullPassRefPtr(T* ptr)
    109             : m_ptr(ptr)
    110         {
    111             ASSERT(m_ptr);
    112             m_ptr->ref();
    113         }
    114 
    115         template <class U> NonNullPassRefPtr(const RefPtr<U>& o)
    116             : m_ptr(o.get())
    117         {
    118             ASSERT(m_ptr);
    119             m_ptr->ref();
    120         }
    121 
    122         NonNullPassRefPtr(const NonNullPassRefPtr& o)
    123             : m_ptr(o.releaseRef())
    124         {
    125             ASSERT(m_ptr);
    126         }
    127 
    128         template <class U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
    129             : m_ptr(o.releaseRef())
    130         {
    131             ASSERT(m_ptr);
    132         }
    133 
    134         template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o)
    135             : m_ptr(o.releaseRef())
    136         {
    137             ASSERT(m_ptr);
    138         }
    139 
    140         ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
    141 
    142         T* get() const { return m_ptr; }
    143 
    144         void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
    145         T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
    146 
    147         T& operator*() const { return *m_ptr; }
    148         T* operator->() const { return m_ptr; }
    149 
    150     private:
    151         mutable T* m_ptr;
    152     };
    153 
    154     template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o)
    155     {
    156         T* optr = o.get();
    157         refIfNotNull(optr);
    158         T* ptr = m_ptr;
    159         m_ptr = optr;
    160         derefIfNotNull(ptr);
    161         return *this;
    162     }
    163 
    164     template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
    165     {
    166         refIfNotNull(optr);
    167         T* ptr = m_ptr;
    168         m_ptr = optr;
    169         derefIfNotNull(ptr);
    170         return *this;
    171     }
    172 
    173     template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
    174     {
    175         T* ptr = m_ptr;
    176         m_ptr = ref.releaseRef();
    177         derefIfNotNull(ptr);
    178         return *this;
    179     }
    180 
    181     template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
    182     {
    183         T* ptr = m_ptr;
    184         m_ptr = ref.releaseRef();
    185         derefIfNotNull(ptr);
    186         return *this;
    187     }
    188 
    189     template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
    190     {
    191         return a.get() == b.get();
    192     }
    193 
    194     template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
    195     {
    196         return a.get() == b.get();
    197     }
    198 
    199     template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
    200     {
    201         return a.get() == b.get();
    202     }
    203 
    204     template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
    205     {
    206         return a.get() == b;
    207     }
    208 
    209     template <typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
    210     {
    211         return a == b.get();
    212     }
    213 
    214     template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
    215     {
    216         return a.get() != b.get();
    217     }
    218 
    219     template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
    220     {
    221         return a.get() != b.get();
    222     }
    223 
    224     template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
    225     {
    226         return a.get() != b.get();
    227     }
    228 
    229     template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
    230     {
    231         return a.get() != b;
    232     }
    233 
    234     template <typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
    235     {
    236         return a != b.get();
    237     }
    238 
    239     template <typename T> inline PassRefPtr<T> adoptRef(T* p)
    240     {
    241         return PassRefPtr<T>(p, true);
    242     }
    243 
    244     template <typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
    245     {
    246         return adoptRef(static_cast<T*>(p.releaseRef()));
    247     }
    248 
    249     template <typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p)
    250     {
    251         return adoptRef(const_cast<T*>(p.releaseRef()));
    252     }
    253 
    254     template <typename T> inline T* getPtr(const PassRefPtr<T>& p)
    255     {
    256         return p.get();
    257     }
    258 
    259 } // namespace WTF
    260 
    261 using WTF::PassRefPtr;
    262 using WTF::NonNullPassRefPtr;
    263 using WTF::adoptRef;
    264 using WTF::static_pointer_cast;
    265 using WTF::const_pointer_cast;
    266 
    267 #endif // WTF_PassRefPtr_h
    268