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 "wtf/Assertions.h"
     25 #include "wtf/NullPtr.h"
     26 #include "wtf/RawPtr.h"
     27 #include "wtf/TypeTraits.h"
     28 
     29 namespace WTF {
     30 
     31     template<typename T> class RefPtr;
     32     template<typename T> class PassRefPtr;
     33     template<typename T> PassRefPtr<T> adoptRef(T*);
     34 
     35     inline void adopted(const void*) { }
     36 
     37     // requireAdoption() is not overloaded for WTF::RefCounted, which has a
     38     // built-in assumption that adoption is required. requireAdoption() is
     39     // for bootstrapping alternate reference count classes that are compatible
     40     // with ReftPtr/PassRefPtr but cannot have adoption checks enabled
     41     // by default, such as skia's SkRefCnt. The purpose of requireAdoption()
     42     // is to enable adoption checks only once it is known that the object will
     43     // be used with RefPtr/PassRefPtr.
     44     inline void requireAdoption(const void*) { }
     45 
     46     template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
     47     {
     48         if (LIKELY(ptr != 0)) {
     49             requireAdoption(ptr);
     50             ptr->ref();
     51         }
     52     }
     53 
     54     template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
     55     {
     56         if (LIKELY(ptr != 0))
     57             ptr->deref();
     58     }
     59 
     60     template<typename T> class PassRefPtr {
     61         WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(PassRefPtr);
     62     public:
     63         PassRefPtr() : m_ptr(0) { }
     64         PassRefPtr(std::nullptr_t) : m_ptr(0) { }
     65         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
     66         template<typename U> PassRefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
     67         explicit PassRefPtr(T& ptr) : m_ptr(&ptr) { m_ptr->ref(); }
     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, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) { }
     73 
     74         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
     75 
     76         template<typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
     77 
     78         T* get() const { return m_ptr; }
     79 
     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         friend PassRefPtr adoptRef<T>(T*);
     92 
     93     private:
     94         enum AdoptRefTag { AdoptRef };
     95         PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) { }
     96 
     97         PassRefPtr& operator=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; }
     98 
     99         mutable T* m_ptr;
    100     };
    101 
    102     template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
    103         : m_ptr(o.get())
    104     {
    105         T* ptr = m_ptr;
    106         refIfNotNull(ptr);
    107     }
    108 
    109     template<typename T> inline T* PassRefPtr<T>::leakRef() const
    110     {
    111         T* ptr = m_ptr;
    112         m_ptr = 0;
    113         return ptr;
    114     }
    115 
    116     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
    117     {
    118         return a.get() == b.get();
    119     }
    120 
    121     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
    122     {
    123         return a.get() == b.get();
    124     }
    125 
    126     template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
    127     {
    128         return a.get() == b.get();
    129     }
    130 
    131     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
    132     {
    133         return a.get() == b;
    134     }
    135 
    136     template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
    137     {
    138         return a == b.get();
    139     }
    140 
    141     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RawPtr<U>& b)
    142     {
    143         return a.get() == b.get();
    144     }
    145 
    146     template<typename T, typename U> inline bool operator==(const RawPtr<T>& a, const PassRefPtr<U>& b)
    147     {
    148         return a.get() == b.get();
    149     }
    150 
    151     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
    152     {
    153         return a.get() != b.get();
    154     }
    155 
    156     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
    157     {
    158         return a.get() != b.get();
    159     }
    160 
    161     template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
    162     {
    163         return a.get() != b.get();
    164     }
    165 
    166     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
    167     {
    168         return a.get() != b;
    169     }
    170 
    171     template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
    172     {
    173         return a != b.get();
    174     }
    175 
    176     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RawPtr<U>& b)
    177     {
    178         return a.get() != b.get();
    179     }
    180 
    181     template<typename T, typename U> inline bool operator!=(const RawPtr<T>& a, const PassRefPtr<U>& b)
    182     {
    183         return a.get() != b.get();
    184     }
    185 
    186     template<typename T> PassRefPtr<T> adoptRef(T* p)
    187     {
    188         adopted(p);
    189         return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef);
    190     }
    191 
    192     template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
    193     {
    194         return adoptRef(static_cast<T*>(p.leakRef()));
    195     }
    196 
    197     template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
    198     {
    199         return p.get();
    200     }
    201 
    202 } // namespace WTF
    203 
    204 using WTF::PassRefPtr;
    205 using WTF::adoptRef;
    206 using WTF::static_pointer_cast;
    207 
    208 #endif // WTF_PassRefPtr_h
    209