initial import
[vuplus_webkit] / Source / JavaScriptCore / wtf / PassRefPtr.h
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         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=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; }
92
93         friend PassRefPtr adoptRef<T>(T*);
94
95         // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
96         T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
97
98     private:
99         // adopting constructor
100         PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
101
102         mutable T* m_ptr;
103     };
104     
105     // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
106     // begins life non-null, and can only become null through a call to leakRef()
107     // or clear().
108
109     // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
110     // if we use inheritance, GCC's optimizer fails to realize that destruction
111     // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
112     // most important code from PassRefPtr.
113     template<typename T> class NonNullPassRefPtr {
114     public:
115         NonNullPassRefPtr(T* ptr)
116             : m_ptr(ptr)
117         {
118             ASSERT(m_ptr);
119             m_ptr->ref();
120         }
121
122         template<typename U> NonNullPassRefPtr(const RefPtr<U>& o)
123             : m_ptr(o.get())
124         {
125             ASSERT(m_ptr);
126             m_ptr->ref();
127         }
128
129         NonNullPassRefPtr(const NonNullPassRefPtr& o)
130             : m_ptr(o.leakRef())
131         {
132             ASSERT(m_ptr);
133         }
134
135         template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
136             : m_ptr(o.leakRef())
137         {
138             ASSERT(m_ptr);
139         }
140
141         template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
142             : m_ptr(o.leakRef())
143         {
144             ASSERT(m_ptr);
145         }
146
147         ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); }
148
149         T* get() const { return m_ptr; }
150
151         T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; }
152
153         T& operator*() const { return *m_ptr; }
154         T* operator->() const { return m_ptr; }
155
156         NonNullPassRefPtr& operator=(const NonNullPassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), NonNullPassRefPtr_should_never_be_assigned_to); return *this; }
157
158         // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
159         T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
160
161     private:
162         mutable T* m_ptr;
163     };
164
165     template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o)
166         : m_ptr(o.get())
167     {
168         T* ptr = m_ptr;
169         refIfNotNull(ptr);
170     }
171
172     template<typename T> inline T* PassRefPtr<T>::leakRef() const
173     {
174         T* ptr = m_ptr;
175         m_ptr = 0;
176         return ptr;
177     }
178
179     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
180     { 
181         return a.get() == b.get(); 
182     }
183
184     template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 
185     { 
186         return a.get() == b.get(); 
187     }
188
189     template<typename T, typename U> inline bool operator==(const RefPtr<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, U* b) 
195     { 
196         return a.get() == b; 
197     }
198     
199     template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) 
200     {
201         return a == b.get(); 
202     }
203     
204     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
205     { 
206         return a.get() != b.get(); 
207     }
208
209     template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 
210     { 
211         return a.get() != b.get(); 
212     }
213
214     template<typename T, typename U> inline bool operator!=(const RefPtr<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, U* b)
220     {
221         return a.get() != b; 
222     }
223
224     template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) 
225     { 
226         return a != b.get(); 
227     }
228     
229     template<typename T> inline PassRefPtr<T> adoptRef(T* p)
230     {
231         adopted(p);
232         return PassRefPtr<T>(p, true);
233     }
234
235     template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 
236     { 
237         return adoptRef(static_cast<T*>(p.leakRef())); 
238     }
239
240     template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) 
241     { 
242         return adoptRef(const_cast<T*>(p.leakRef())); 
243     }
244
245     template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
246     {
247         return p.get();
248     }
249
250 } // namespace WTF
251
252 using WTF::PassRefPtr;
253 using WTF::NonNullPassRefPtr;
254 using WTF::adoptRef;
255 using WTF::static_pointer_cast;
256 using WTF::const_pointer_cast;
257
258 #endif // WTF_PassRefPtr_h