Home | History | Annotate | Download | only in gobject
      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:
     46     GRefPtr() : m_ptr(0) { }
     47 
     48     GRefPtr(T* ptr)
     49         : m_ptr(ptr)
     50     {
     51         if (ptr)
     52             refGPtr(ptr);
     53     }
     54 
     55     GRefPtr(const GRefPtr& o)
     56         : m_ptr(o.m_ptr)
     57     {
     58         if (T* ptr = m_ptr)
     59             refGPtr(ptr);
     60     }
     61 
     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 
     69     ~GRefPtr()
     70     {
     71         if (T* ptr = m_ptr)
     72             derefGPtr(ptr);
     73     }
     74 
     75     void clear()
     76     {
     77         T* ptr = m_ptr;
     78         m_ptr = 0;
     79         if (ptr)
     80             derefGPtr(ptr);
     81     }
     82 
     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.
     91     GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
     92     bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
     93 
     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;
    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:
    112     static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
    113     // Adopting constructor.
    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 
    142 template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o)
    143 {
    144     std::swap(m_ptr, o.m_ptr);
    145 }
    146 
    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 
    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 
    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 
    192 template <typename T> inline T* getPtr(const GRefPtr<T>& p)
    193 {
    194     return p.get();
    195 }
    196 
    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 
    209 template <typename T> inline T* refGPtr(T* ptr)
    210 {
    211     if (ptr)
    212         g_object_ref_sink(ptr);
    213     return ptr;
    214 }
    215 
    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