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 "wtf/Assertions.h"
25#include "wtf/NullPtr.h"
26#include "wtf/RawPtr.h"
27#include "wtf/TypeTraits.h"
28
29namespace WTF {
30
31    template<typename T> class RefPtr;
32    template<typename T> class PassRefPtr;
33    template<typename T> PassRefPtr<T> adoptRef(T*);
34
35    inline void adopted(const void*) { }
36
37    // requireAdoption() is not overloaded for WTF::RefCounted, which has a
38    // built-in assumption that adoption is required. requireAdoption() is
39    // for bootstrapping alternate reference count classes that are compatible
40    // with ReftPtr/PassRefPtr but cannot have adoption checks enabled
41    // by default, such as skia's SkRefCnt. The purpose of requireAdoption()
42    // is to enable adoption checks only once it is known that the object will
43    // be used with RefPtr/PassRefPtr.
44    inline void requireAdoption(const void*) { }
45
46    template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
47    {
48        if (LIKELY(ptr != 0)) {
49            requireAdoption(ptr);
50            ptr->ref();
51        }
52    }
53
54    template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
55    {
56        if (LIKELY(ptr != 0))
57            ptr->deref();
58    }
59
60    template<typename T> class PassRefPtr {
61        WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(PassRefPtr);
62    public:
63        PassRefPtr() : m_ptr(0) { }
64        PassRefPtr(std::nullptr_t) : m_ptr(0) { }
65        PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
66        template<typename U> PassRefPtr(const RawPtr<U>& ptr, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(ptr.get()) { refIfNotNull(m_ptr); }
67        explicit PassRefPtr(T& ptr) : m_ptr(&ptr) { m_ptr->ref(); }
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, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.leakRef()) { }
73
74        ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
75
76        template<typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
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        friend PassRefPtr adoptRef<T>(T*);
92
93    private:
94        enum AdoptRefTag { AdoptRef };
95        PassRefPtr(T* ptr, AdoptRefTag) : m_ptr(ptr) { }
96
97        PassRefPtr& operator=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; }
98
99        mutable T* m_ptr;
100    };
101
102    template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDefn(U, T))
103        : m_ptr(o.get())
104    {
105        T* ptr = m_ptr;
106        refIfNotNull(ptr);
107    }
108
109    template<typename T> inline T* PassRefPtr<T>::leakRef() const
110    {
111        T* ptr = m_ptr;
112        m_ptr = 0;
113        return ptr;
114    }
115
116    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
117    {
118        return a.get() == b.get();
119    }
120
121    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b)
122    {
123        return a.get() == b.get();
124    }
125
126    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b)
127    {
128        return a.get() == b.get();
129    }
130
131    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b)
132    {
133        return a.get() == b;
134    }
135
136    template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b)
137    {
138        return a == b.get();
139    }
140
141    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RawPtr<U>& b)
142    {
143        return a.get() == b.get();
144    }
145
146    template<typename T, typename U> inline bool operator==(const RawPtr<T>& a, const PassRefPtr<U>& b)
147    {
148        return a.get() == b.get();
149    }
150
151    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b)
152    {
153        return a.get() != b.get();
154    }
155
156    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b)
157    {
158        return a.get() != b.get();
159    }
160
161    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b)
162    {
163        return a.get() != b.get();
164    }
165
166    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
167    {
168        return a.get() != b;
169    }
170
171    template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b)
172    {
173        return a != b.get();
174    }
175
176    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RawPtr<U>& b)
177    {
178        return a.get() != b.get();
179    }
180
181    template<typename T, typename U> inline bool operator!=(const RawPtr<T>& a, const PassRefPtr<U>& b)
182    {
183        return a.get() != b.get();
184    }
185
186    template<typename T> PassRefPtr<T> adoptRef(T* p)
187    {
188        adopted(p);
189        return PassRefPtr<T>(p, PassRefPtr<T>::AdoptRef);
190    }
191
192    template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p)
193    {
194        return adoptRef(static_cast<T*>(p.leakRef()));
195    }
196
197    template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
198    {
199        return p.get();
200    }
201
202} // namespace WTF
203
204using WTF::PassRefPtr;
205using WTF::adoptRef;
206using WTF::static_pointer_cast;
207
208#endif // WTF_PassRefPtr_h
209