• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
adopted(const void *)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.
requireAdoption(const void *)44     inline void requireAdoption(const void*) { }
45 
refIfNotNull(T * ptr)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 
derefIfNotNull(T * ptr)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:
PassRefPtr()63         PassRefPtr() : m_ptr(0) { }
PassRefPtr(std::nullptr_t)64         PassRefPtr(std::nullptr_t) : m_ptr(0) { }
PassRefPtr(T * ptr)65         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
PassRefPtr(const RawPtr<U> & ptr,EnsurePtrConvertibleArgDecl (U,T))66         template<typename U> PassRefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
PassRefPtr(T & 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.
PassRefPtr(const PassRefPtr & o)71         PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
PassRefPtr(const PassRefPtr<U> & o,EnsurePtrConvertibleArgDecl (U,T))72         template<typename U> PassRefPtr(const PassRefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) { }
73 
~PassRefPtr()74         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
75 
76         template<typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
77 
get()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);
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 };
PassRefPtr(T * ptr,AdoptRefTag)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 
PassRefPtr(const RefPtr<U> & o,EnsurePtrConvertibleArgDefn (U,T))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 
leakRef()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 
adoptRef(T * p)186     template<typename T> PassRefPtr<T> adoptRef(T* p)
187     {
188         adopted(p);
189         return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef);
190     }
191 
static_pointer_cast(const PassRefPtr<U> & p)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 
getPtr(const PassRefPtr<T> & p)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