fc3ac9cdc02ddfabf01350f9fd3cda34da0cce01
[WebKit-https.git] / Source / WTF / wtf / WeakPtr.h
1 /*
2  * Copyright (C) 2013 Google, Inc. All Rights Reserved.
3  * Copyright (C) 2015, 2017 Apple Inc. All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #pragma once
28
29 #include <wtf/Noncopyable.h>
30 #include <wtf/Ref.h>
31 #include <wtf/ThreadSafeRefCounted.h>
32 #include <wtf/Threading.h>
33
34 namespace WTF {
35
36 // Testing interface for TestWebKitAPI
37 #ifndef DID_CREATE_WEAK_REFERENCE
38 #define DID_CREATE_WEAK_REFERENCE(p)
39 #endif
40 #ifndef WILL_DESTROY_WEAK_REFERENCE
41 #define WILL_DESTROY_WEAK_REFERENCE(p)
42 #endif
43
44 template<typename> class WeakHashSet;
45 template<typename> class WeakPtr;
46 template<typename> class WeakPtrFactory;
47
48 // Note: WeakReference is an implementation detail, and should not be used directly.
49 class WeakReference : public ThreadSafeRefCounted<WeakReference> {
50     WTF_MAKE_NONCOPYABLE(WeakReference);
51     WTF_MAKE_FAST_ALLOCATED;
52 public:
53     template<typename T> static Ref<WeakReference> create(T* ptr) { return adoptRef(*new WeakReference(ptr)); }
54
55     ~WeakReference()
56     {
57         WILL_DESTROY_WEAK_REFERENCE(m_ptr);
58     }
59
60     template<typename T, typename WeakValueType> T* get() const { return static_cast<T*>(static_cast<WeakValueType*>(m_ptr)); }
61     explicit operator bool() const { return m_ptr; }
62
63     void clear() { m_ptr = nullptr; }
64
65 private:
66     template<typename T> explicit WeakReference(T* ptr)
67         : m_ptr(ptr)
68     {
69         DID_CREATE_WEAK_REFERENCE(ptr);
70     }
71
72     void* m_ptr;
73 };
74
75 template<typename T>
76 class WeakPtr {
77     WTF_MAKE_FAST_ALLOCATED;
78 public:
79     WeakPtr() { }
80     WeakPtr(std::nullptr_t) { }
81     template<typename U> WeakPtr(const WeakPtr<U>&);
82     template<typename U> WeakPtr(WeakPtr<U>&&);
83
84     T* get() const { return m_ref ? m_ref->template get<T, typename T::WeakValueType>() : nullptr; }
85     explicit operator bool() const { return m_ref && *m_ref; }
86
87     WeakPtr& operator=(std::nullptr_t) { m_ref = nullptr; return *this; }
88     template<typename U> WeakPtr& operator=(const WeakPtr<U>&);
89     template<typename U> WeakPtr& operator=(WeakPtr<U>&&);
90
91     T* operator->() const { return get(); }
92     T& operator*() const { return *get(); }
93
94     void clear() { m_ref = nullptr; }
95
96 private:
97     explicit WeakPtr(Ref<WeakReference>&& ref) : m_ref(std::move(ref)) { }
98     template<typename> friend class WeakHashSet;
99     template<typename> friend class WeakPtr;
100     template<typename> friend class WeakPtrFactory;
101     template<typename U> friend WeakPtr<U> makeWeakPtr(U&);
102
103     RefPtr<WeakReference> m_ref;
104 };
105
106 // Note: you probably want to inherit from CanMakeWeakPtr rather than use this directly.
107 template<typename T>
108 class WeakPtrFactory {
109     WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>);
110     WTF_MAKE_FAST_ALLOCATED;
111 public:
112     WeakPtrFactory() = default;
113     ~WeakPtrFactory()
114     {
115         if (!m_ref)
116             return;
117         m_ref->clear();
118     }
119
120     WeakPtr<T> createWeakPtr(T& ptr) const
121     {
122         if (!m_ref)
123             m_ref = WeakReference::create(&ptr);
124         return WeakPtr<T>(makeRef(*m_ref));
125     }
126
127     WeakPtr<const T> createWeakPtr(const T& ptr) const
128     {
129         if (!m_ref)
130             m_ref = WeakReference::create(const_cast<T*>(&ptr));
131         return WeakPtr<T>(makeRef(*m_ref));
132     }
133
134     void revokeAll()
135     {
136         if (!m_ref)
137             return;
138
139         m_ref->clear();
140         m_ref = nullptr;
141     }
142
143 private:
144     template<typename> friend class WeakHashSet;
145
146     mutable RefPtr<WeakReference> m_ref;
147 };
148
149 template<typename T> class CanMakeWeakPtr {
150 public:
151     typedef T WeakValueType;
152
153     const WeakPtrFactory<T>& weakPtrFactory() const { return m_weakFactory; }
154     WeakPtrFactory<T>& weakPtrFactory() { return m_weakFactory; }
155
156 private:
157     WeakPtrFactory<T> m_weakFactory;
158 };
159
160 template<typename T, typename U> inline WeakReference* weak_reference_cast(WeakReference* weakReference)
161 {
162     UNUSED_VARIABLE(static_cast<T*>(static_cast<typename U::WeakValueType*>(nullptr))); // Verify that casting is valid.
163     return weakReference;
164 }
165
166 template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(const WeakPtr<U>& o)
167     : m_ref(weak_reference_cast<T, U>(o.m_ref.get()))
168 {
169 }
170
171 template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(WeakPtr<U>&& o)
172     : m_ref(adoptRef(weak_reference_cast<T, U>(o.m_ref.leakRef())))
173 {
174 }
175
176 template<typename T> template<typename U> inline WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr<U>& o)
177 {
178     m_ref = weak_reference_cast<T, U>(o.m_ref.get());
179     return *this;
180 }
181
182 template<typename T> template<typename U> inline WeakPtr<T>& WeakPtr<T>::operator=(WeakPtr<U>&& o)
183 {
184     m_ref = adoptRef(weak_reference_cast<T, U>(o.m_ref.leakRef()));
185     return *this;
186 }
187
188 template<typename T> inline WeakPtr<T> makeWeakPtr(T& ref)
189 {
190     return { ref.weakPtrFactory().createWeakPtr(ref) };
191 }
192
193 template<typename T> inline WeakPtr<T> makeWeakPtr(T* ptr)
194 {
195     if (!ptr)
196         return { };
197     return makeWeakPtr(*ptr);
198 }
199
200 template<typename T, typename U> inline bool operator==(const WeakPtr<T>& a, const WeakPtr<U>& b)
201 {
202     return a.get() == b.get();
203 }
204
205 template<typename T, typename U> inline bool operator==(const WeakPtr<T>& a, U* b)
206 {
207     return a.get() == b;
208 }
209
210 template<typename T, typename U> inline bool operator==(T* a, const WeakPtr<U>& b)
211 {
212     return a == b.get();
213 }
214
215 template<typename T, typename U> inline bool operator!=(const WeakPtr<T>& a, const WeakPtr<U>& b)
216 {
217     return a.get() != b.get();
218 }
219
220 template<typename T, typename U> inline bool operator!=(const WeakPtr<T>& a, U* b)
221 {
222     return a.get() != b;
223 }
224
225 template<typename T, typename U> inline bool operator!=(T* a, const WeakPtr<U>& b)
226 {
227     return a != b.get();
228 }
229
230 } // namespace WTF
231
232 using WTF::CanMakeWeakPtr;
233 using WTF::WeakPtr;
234 using WTF::WeakPtrFactory;
235 using WTF::WeakReference;
236 using WTF::makeWeakPtr;