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