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/RefPtr.h> 29#include <algorithm> 30 31extern "C" void g_object_unref(gpointer); 32extern "C" gpointer g_object_ref_sink(gpointer); 33 34namespace WTF { 35 36enum GRefPtrAdoptType { GRefPtrAdopt }; 37template <typename T> inline T* refGPtr(T*); 38template <typename T> inline void derefGPtr(T*); 39template <typename T> class GRefPtr; 40template <typename T> GRefPtr<T> adoptGRef(T*); 41 42template <typename T> class GRefPtr { 43public: 44 GRefPtr() : m_ptr(0) { } 45 46 GRefPtr(T* ptr) 47 : m_ptr(ptr) 48 { 49 if (ptr) 50 refGPtr(ptr); 51 } 52 53 GRefPtr(const GRefPtr& o) 54 : m_ptr(o.m_ptr) 55 { 56 if (T* ptr = m_ptr) 57 refGPtr(ptr); 58 } 59 60 template <typename U> GRefPtr(const GRefPtr<U>& o) 61 : m_ptr(o.get()) 62 { 63 if (T* ptr = m_ptr) 64 refGPtr(ptr); 65 } 66 67 ~GRefPtr() 68 { 69 if (T* ptr = m_ptr) 70 derefGPtr(ptr); 71 } 72 73 void clear() 74 { 75 T* ptr = m_ptr; 76 m_ptr = 0; 77 if (ptr) 78 derefGPtr(ptr); 79 } 80 81 T* leakRef() WARN_UNUSED_RETURN 82 { 83 T* ptr = m_ptr; 84 m_ptr = 0; 85 return ptr; 86 } 87 88 T*& outPtr() 89 { 90 ASSERT(!m_ptr); 91 return m_ptr; 92 } 93 94 // Hash table deleted values, which are only constructed and never copied or destroyed. 95 GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } 96 bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } 97 98 T* get() const { return m_ptr; } 99 T& operator*() const { return *m_ptr; } 100 ALWAYS_INLINE T* operator->() const { return m_ptr; } 101 102 bool operator!() const { return !m_ptr; } 103 104 // This conversion operator allows implicit conversion to bool but not to other integer types. 105 typedef T* GRefPtr::*UnspecifiedBoolType; 106 operator UnspecifiedBoolType() const { return m_ptr ? &GRefPtr::m_ptr : 0; } 107 108 GRefPtr& operator=(const GRefPtr&); 109 GRefPtr& operator=(T*); 110 template <typename U> GRefPtr& operator=(const GRefPtr<U>&); 111 112 void swap(GRefPtr&); 113 friend GRefPtr adoptGRef<T>(T*); 114 115private: 116 static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } 117 // Adopting constructor. 118 GRefPtr(T* ptr, GRefPtrAdoptType) : m_ptr(ptr) {} 119 120 T* m_ptr; 121}; 122 123template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(const GRefPtr<T>& o) 124{ 125 T* optr = o.get(); 126 if (optr) 127 refGPtr(optr); 128 T* ptr = m_ptr; 129 m_ptr = optr; 130 if (ptr) 131 derefGPtr(ptr); 132 return *this; 133} 134 135template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(T* optr) 136{ 137 T* ptr = m_ptr; 138 if (optr) 139 refGPtr(optr); 140 m_ptr = optr; 141 if (ptr) 142 derefGPtr(ptr); 143 return *this; 144} 145 146template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o) 147{ 148 std::swap(m_ptr, o.m_ptr); 149} 150 151template <class T> inline void swap(GRefPtr<T>& a, GRefPtr<T>& b) 152{ 153 a.swap(b); 154} 155 156template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, const GRefPtr<U>& b) 157{ 158 return a.get() == b.get(); 159} 160 161template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, U* b) 162{ 163 return a.get() == b; 164} 165 166template <typename T, typename U> inline bool operator==(T* a, const GRefPtr<U>& b) 167{ 168 return a == b.get(); 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 GRefPtr<T> static_pointer_cast(const GRefPtr<U>& p) 187{ 188 return GRefPtr<T>(static_cast<T*>(p.get())); 189} 190 191template <typename T, typename U> inline GRefPtr<T> const_pointer_cast(const GRefPtr<U>& p) 192{ 193 return GRefPtr<T>(const_cast<T*>(p.get())); 194} 195 196template <typename T> inline T* getPtr(const GRefPtr<T>& p) 197{ 198 return p.get(); 199} 200 201template <typename T> GRefPtr<T> adoptGRef(T* p) 202{ 203 return GRefPtr<T>(p, GRefPtrAdopt); 204} 205 206template <> WTF_EXPORT_PRIVATE GHashTable* refGPtr(GHashTable* ptr); 207template <> WTF_EXPORT_PRIVATE void derefGPtr(GHashTable* ptr); 208template <> WTF_EXPORT_PRIVATE GMainContext* refGPtr(GMainContext* ptr); 209template <> WTF_EXPORT_PRIVATE void derefGPtr(GMainContext* ptr); 210template <> WTF_EXPORT_PRIVATE GMainLoop* refGPtr(GMainLoop* ptr); 211template <> WTF_EXPORT_PRIVATE void derefGPtr(GMainLoop* ptr); 212template <> WTF_EXPORT_PRIVATE GVariant* refGPtr(GVariant* ptr); 213template <> WTF_EXPORT_PRIVATE void derefGPtr(GVariant* ptr); 214template <> WTF_EXPORT_PRIVATE GSource* refGPtr(GSource* ptr); 215template <> WTF_EXPORT_PRIVATE void derefGPtr(GSource* ptr); 216template <> WTF_EXPORT_PRIVATE GPtrArray* refGPtr(GPtrArray*); 217template <> WTF_EXPORT_PRIVATE void derefGPtr(GPtrArray*); 218template <> WTF_EXPORT_PRIVATE GByteArray* refGPtr(GByteArray*); 219template <> WTF_EXPORT_PRIVATE void derefGPtr(GByteArray*); 220template <> WTF_EXPORT_PRIVATE GBytes* refGPtr(GBytes*); 221template <> WTF_EXPORT_PRIVATE void derefGPtr(GBytes*); 222template <> WTF_EXPORT_PRIVATE GClosure* refGPtr(GClosure*); 223template <> WTF_EXPORT_PRIVATE void derefGPtr(GClosure*); 224 225template <typename T> inline T* refGPtr(T* ptr) 226{ 227 if (ptr) 228 g_object_ref_sink(ptr); 229 return ptr; 230} 231 232template <typename T> inline void derefGPtr(T* ptr) 233{ 234 if (ptr) 235 g_object_unref(ptr); 236} 237 238} // namespace WTF 239 240using WTF::GRefPtr; 241using WTF::adoptGRef; 242 243#endif // USE(GLIB) 244 245#endif // WTF_GRefPtr_h 246