1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora Ltd.
4 * Copyright (C) 2009 Martin Robinson
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifndef WTF_GRefPtr_h
24 #define WTF_GRefPtr_h
25
26 #if ENABLE(GLIB_SUPPORT)
27
28 #include "AlwaysInline.h"
29 #include "GRefPtr.h"
30 #include "RefPtr.h"
31 #include <algorithm>
32
33 extern "C" void g_object_unref(gpointer);
34 extern "C" gpointer g_object_ref_sink(gpointer);
35
36 namespace WTF {
37
38 enum GRefPtrAdoptType { GRefPtrAdopt };
39 template <typename T> inline T* refGPtr(T*);
40 template <typename T> inline void derefGPtr(T*);
41 template <typename T> class GRefPtr;
42 template <typename T> GRefPtr<T> adoptGRef(T*);
43
44 template <typename T> class GRefPtr {
45 public:
GRefPtr()46 GRefPtr() : m_ptr(0) { }
47
GRefPtr(T * ptr)48 GRefPtr(T* ptr)
49 : m_ptr(ptr)
50 {
51 if (ptr)
52 refGPtr(ptr);
53 }
54
GRefPtr(const GRefPtr & o)55 GRefPtr(const GRefPtr& o)
56 : m_ptr(o.m_ptr)
57 {
58 if (T* ptr = m_ptr)
59 refGPtr(ptr);
60 }
61
GRefPtr(const GRefPtr<U> & o)62 template <typename U> GRefPtr(const GRefPtr<U>& o)
63 : m_ptr(o.get())
64 {
65 if (T* ptr = m_ptr)
66 refGPtr(ptr);
67 }
68
~GRefPtr()69 ~GRefPtr()
70 {
71 if (T* ptr = m_ptr)
72 derefGPtr(ptr);
73 }
74
clear()75 void clear()
76 {
77 T* ptr = m_ptr;
78 m_ptr = 0;
79 if (ptr)
80 derefGPtr(ptr);
81 }
82
leakRef()83 T* leakRef() WARN_UNUSED_RETURN
84 {
85 T* ptr = m_ptr;
86 m_ptr = 0;
87 return ptr;
88 }
89
90 // Hash table deleted values, which are only constructed and never copied or destroyed.
GRefPtr(HashTableDeletedValueType)91 GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
isHashTableDeletedValue()92 bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
93
get()94 T* get() const { return m_ptr; }
95 T& operator*() const { return *m_ptr; }
96 ALWAYS_INLINE T* operator->() const { return m_ptr; }
97
98 bool operator!() const { return !m_ptr; }
99
100 // This conversion operator allows implicit conversion to bool but not to other integer types.
101 typedef T* GRefPtr::*UnspecifiedBoolType;
UnspecifiedBoolType()102 operator UnspecifiedBoolType() const { return m_ptr ? &GRefPtr::m_ptr : 0; }
103
104 GRefPtr& operator=(const GRefPtr&);
105 GRefPtr& operator=(T*);
106 template <typename U> GRefPtr& operator=(const GRefPtr<U>&);
107
108 void swap(GRefPtr&);
109 friend GRefPtr adoptGRef<T>(T*);
110
111 private:
hashTableDeletedValue()112 static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
113 // Adopting constructor.
GRefPtr(T * ptr,GRefPtrAdoptType)114 GRefPtr(T* ptr, GRefPtrAdoptType) : m_ptr(ptr) {}
115
116 T* m_ptr;
117 };
118
119 template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(const GRefPtr<T>& o)
120 {
121 T* optr = o.get();
122 if (optr)
123 refGPtr(optr);
124 T* ptr = m_ptr;
125 m_ptr = optr;
126 if (ptr)
127 derefGPtr(ptr);
128 return *this;
129 }
130
131 template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(T* optr)
132 {
133 T* ptr = m_ptr;
134 if (optr)
135 refGPtr(optr);
136 m_ptr = optr;
137 if (ptr)
138 derefGPtr(ptr);
139 return *this;
140 }
141
swap(GRefPtr<T> & o)142 template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o)
143 {
144 std::swap(m_ptr, o.m_ptr);
145 }
146
swap(GRefPtr<T> & a,GRefPtr<T> & b)147 template <class T> inline void swap(GRefPtr<T>& a, GRefPtr<T>& b)
148 {
149 a.swap(b);
150 }
151
152 template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, const GRefPtr<U>& b)
153 {
154 return a.get() == b.get();
155 }
156
157 template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, U* b)
158 {
159 return a.get() == b;
160 }
161
162 template <typename T, typename U> inline bool operator==(T* a, const GRefPtr<U>& b)
163 {
164 return a == b.get();
165 }
166
167 template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, const GRefPtr<U>& b)
168 {
169 return a.get() != b.get();
170 }
171
172 template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, U* b)
173 {
174 return a.get() != b;
175 }
176
177 template <typename T, typename U> inline bool operator!=(T* a, const GRefPtr<U>& b)
178 {
179 return a != b.get();
180 }
181
static_pointer_cast(const GRefPtr<U> & p)182 template <typename T, typename U> inline GRefPtr<T> static_pointer_cast(const GRefPtr<U>& p)
183 {
184 return GRefPtr<T>(static_cast<T*>(p.get()));
185 }
186
const_pointer_cast(const GRefPtr<U> & p)187 template <typename T, typename U> inline GRefPtr<T> const_pointer_cast(const GRefPtr<U>& p)
188 {
189 return GRefPtr<T>(const_cast<T*>(p.get()));
190 }
191
getPtr(const GRefPtr<T> & p)192 template <typename T> inline T* getPtr(const GRefPtr<T>& p)
193 {
194 return p.get();
195 }
196
adoptGRef(T * p)197 template <typename T> GRefPtr<T> adoptGRef(T* p)
198 {
199 return GRefPtr<T>(p, GRefPtrAdopt);
200 }
201
202 template <> GHashTable* refGPtr(GHashTable* ptr);
203 template <> void derefGPtr(GHashTable* ptr);
204 template <> GVariant* refGPtr(GVariant* ptr);
205 template <> void derefGPtr(GVariant* ptr);
206 template <> GSource* refGPtr(GSource* ptr);
207 template <> void derefGPtr(GSource* ptr);
208
refGPtr(T * ptr)209 template <typename T> inline T* refGPtr(T* ptr)
210 {
211 if (ptr)
212 g_object_ref_sink(ptr);
213 return ptr;
214 }
215
derefGPtr(T * ptr)216 template <typename T> inline void derefGPtr(T* ptr)
217 {
218 if (ptr)
219 g_object_unref(ptr);
220 }
221
222 } // namespace WTF
223
224 using WTF::GRefPtr;
225 using WTF::adoptGRef;
226
227 #endif // ENABLE(GLIB_SUPPORT)
228
229 #endif // WTF_GRefPtr_h
230