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 USE(GLIB)
27
28#include <wtf/HashTraits.h>
29#include <algorithm>
30#include <glib.h>
31
32extern "C" void g_object_unref(gpointer);
33extern "C" gpointer g_object_ref_sink(gpointer);
34
35namespace WTF {
36
37enum GRefPtrAdoptType { GRefPtrAdopt };
38template <typename T> inline T* refGPtr(T*);
39template <typename T> inline void derefGPtr(T*);
40template <typename T> class GRefPtr;
41template <typename T> GRefPtr<T> adoptGRef(T*);
42
43template <typename T> class GRefPtr {
44public:
45 typedef T ValueType;
46 typedef ValueType* PtrType;
47
48 GRefPtr() : m_ptr(0) { }
49
50 GRefPtr(T* ptr)
51 : m_ptr(ptr)
52 {
53 if (ptr)
54 refGPtr(ptr);
55 }
56
57 GRefPtr(const GRefPtr& o)
58 : m_ptr(o.m_ptr)
59 {
60 if (T* ptr = m_ptr)
61 refGPtr(ptr);
62 }
63
64 template <typename U> GRefPtr(const GRefPtr<U>& o)
65 : m_ptr(o.get())
66 {
67 if (T* ptr = m_ptr)
68 refGPtr(ptr);
69 }
70
71 GRefPtr(GRefPtr&& o) : m_ptr(o.leakRef()) { }
72 template <typename U> GRefPtr(GRefPtr<U>&& o) : m_ptr(o.leakRef()) { }
73
74 ~GRefPtr()
75 {
76 if (T* ptr = m_ptr)
77 derefGPtr(ptr);
78 }
79
80 void clear()
81 {
82 T* ptr = m_ptr;
83 m_ptr = 0;
84 if (ptr)
85 derefGPtr(ptr);
86 }
87
88 T* leakRef() WARN_UNUSED_RETURN
89 {
90 T* ptr = m_ptr;
91 m_ptr = 0;
92 return ptr;
93 }
94
95 T*& outPtr()
96 {
97 ASSERT(!m_ptr);
98 return m_ptr;
99 }
100
101 // Hash table deleted values, which are only constructed and never copied or destroyed.
102 GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
103 bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
104
105 T* get() const { return m_ptr; }
106 T& operator*() const { return *m_ptr; }
107 ALWAYS_INLINE T* operator->() const { return m_ptr; }
108
109 bool operator!() const { return !m_ptr; }
110
111 // This conversion operator allows implicit conversion to bool but not to other integer types.
112 typedef T* GRefPtr::*UnspecifiedBoolType;
113 operator UnspecifiedBoolType() const { return m_ptr ? &GRefPtr::m_ptr : 0; }
114
115 GRefPtr& operator=(const GRefPtr&);
116 GRefPtr& operator=(GRefPtr&&);
117 GRefPtr& operator=(T*);
118 template <typename U> GRefPtr& operator=(const GRefPtr<U>&);
119
120 void swap(GRefPtr&);
121 friend GRefPtr adoptGRef<T>(T*);
122
123private:
124 static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
125 // Adopting constructor.
126 GRefPtr(T* ptr, GRefPtrAdoptType) : m_ptr(ptr) {}
127
128 T* m_ptr;
129};
130
131template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(const GRefPtr<T>& o)
132{
133 T* optr = o.get();
134 if (optr)
135 refGPtr(optr);
136 T* ptr = m_ptr;
137 m_ptr = optr;
138 if (ptr)
139 derefGPtr(ptr);
140 return *this;
141}
142
143template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(GRefPtr<T>&& o)
144{
145 GRefPtr ptr = WTFMove(o);
146 swap(ptr);
147 return *this;
148}
149
150template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(T* optr)
151{
152 T* ptr = m_ptr;
153 if (optr)
154 refGPtr(optr);
155 m_ptr = optr;
156 if (ptr)
157 derefGPtr(ptr);
158 return *this;
159}
160
161template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o)
162{
163 std::swap(m_ptr, o.m_ptr);
164}
165
166template <class T> inline void swap(GRefPtr<T>& a, GRefPtr<T>& b)
167{
168 a.swap(b);
169}
170
171template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, const GRefPtr<U>& b)
172{
173 return a.get() == b.get();
174}
175
176template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, U* b)
177{
178 return a.get() == b;
179}
180
181template <typename T, typename U> inline bool operator==(T* a, const GRefPtr<U>& b)
182{
183 return a == b.get();
184}
185
186template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, const GRefPtr<U>& b)
187{
188 return a.get() != b.get();
189}
190
191template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, U* b)
192{
193 return a.get() != b;
194}
195
196template <typename T, typename U> inline bool operator!=(T* a, const GRefPtr<U>& b)
197{
198 return a != b.get();
199}
200
201template <typename T, typename U> inline GRefPtr<T> static_pointer_cast(const GRefPtr<U>& p)
202{
203 return GRefPtr<T>(static_cast<T*>(p.get()));
204}
205
206template <typename T, typename U> inline GRefPtr<T> const_pointer_cast(const GRefPtr<U>& p)
207{
208 return GRefPtr<T>(const_cast<T*>(p.get()));
209}
210
211template <typename T> struct IsSmartPtr<GRefPtr<T>> {
212 static const bool value = true;
213};
214
215template <typename T> GRefPtr<T> adoptGRef(T* p)
216{
217 return GRefPtr<T>(p, GRefPtrAdopt);
218}
219
220template <> WTF_EXPORT_PRIVATE GHashTable* refGPtr(GHashTable* ptr);
221template <> WTF_EXPORT_PRIVATE void derefGPtr(GHashTable* ptr);
222template <> WTF_EXPORT_PRIVATE GMainContext* refGPtr(GMainContext* ptr);
223template <> WTF_EXPORT_PRIVATE void derefGPtr(GMainContext* ptr);
224template <> WTF_EXPORT_PRIVATE GMainLoop* refGPtr(GMainLoop* ptr);
225template <> WTF_EXPORT_PRIVATE void derefGPtr(GMainLoop* ptr);
226template <> WTF_EXPORT_PRIVATE GVariant* refGPtr(GVariant* ptr);
227template <> WTF_EXPORT_PRIVATE void derefGPtr(GVariant* ptr);
228template <> WTF_EXPORT_PRIVATE GVariantBuilder* refGPtr(GVariantBuilder* ptr);
229template <> WTF_EXPORT_PRIVATE void derefGPtr(GVariantBuilder* ptr);
230template <> WTF_EXPORT_PRIVATE GSource* refGPtr(GSource* ptr);
231template <> WTF_EXPORT_PRIVATE void derefGPtr(GSource* ptr);
232template <> WTF_EXPORT_PRIVATE GPtrArray* refGPtr(GPtrArray*);
233template <> WTF_EXPORT_PRIVATE void derefGPtr(GPtrArray*);
234template <> WTF_EXPORT_PRIVATE GByteArray* refGPtr(GByteArray*);
235template <> WTF_EXPORT_PRIVATE void derefGPtr(GByteArray*);
236template <> WTF_EXPORT_PRIVATE GBytes* refGPtr(GBytes*);
237template <> WTF_EXPORT_PRIVATE void derefGPtr(GBytes*);
238template <> WTF_EXPORT_PRIVATE GClosure* refGPtr(GClosure*);
239template <> WTF_EXPORT_PRIVATE void derefGPtr(GClosure*);
240template <> WTF_EXPORT_PRIVATE GRegex* refGPtr(GRegex*);
241template <> WTF_EXPORT_PRIVATE void derefGPtr(GRegex*);
242template <> WTF_EXPORT_PRIVATE GMappedFile* refGPtr(GMappedFile*);
243template <> WTF_EXPORT_PRIVATE void derefGPtr(GMappedFile*);
244
245template <typename T> inline T* refGPtr(T* ptr)
246{
247 if (ptr)
248 g_object_ref_sink(ptr);
249 return ptr;
250}
251
252template <typename T> inline void derefGPtr(T* ptr)
253{
254 if (ptr)
255 g_object_unref(ptr);
256}
257
258template<typename P> struct DefaultHash<GRefPtr<P>> { typedef PtrHash<GRefPtr<P>> Hash; };
259
260template<typename P> struct HashTraits<GRefPtr<P>> : SimpleClassHashTraits<GRefPtr<P>> {
261 static P* emptyValue() { return nullptr; }
262
263 typedef P* PeekType;
264 static PeekType peek(const GRefPtr<P>& value) { return value.get(); }
265 static PeekType peek(P* value) { return value; }
266
267 static void customDeleteBucket(GRefPtr<P>& value)
268 {
269 // See unique_ptr's customDeleteBucket() for an explanation.
270 ASSERT(!SimpleClassHashTraits<GRefPtr<P>>::isDeletedValue(value));
271 auto valueToBeDestroyed = WTFMove(value);
272 SimpleClassHashTraits<GRefPtr<P>>::constructDeletedValue(value);
273 }
274};
275
276} // namespace WTF
277
278using WTF::GRefPtr;
279using WTF::adoptGRef;
280
281#endif // USE(GLIB)
282
283#endif // WTF_GRefPtr_h
284