Some WeakPtr cleanup
[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_PTR_IMPL
38 #define DID_CREATE_WEAK_PTR_IMPL(p)
39 #endif
40 #ifndef WILL_DESTROY_WEAK_PTR_IMPL
41 #define WILL_DESTROY_WEAK_PTR_IMPL(p)
42 #endif
43
44 template<typename> class WeakHashSet;
45 template<typename> class WeakPtr;
46 template<typename> class WeakPtrFactory;
47
48 class WeakPtrImpl : public ThreadSafeRefCounted<WeakPtrImpl> {
49     WTF_MAKE_NONCOPYABLE(WeakPtrImpl);
50     WTF_MAKE_FAST_ALLOCATED;
51 public:
52     template<typename T> static Ref<WeakPtrImpl> create(T* ptr)
53     {
54         return adoptRef(*new WeakPtrImpl(ptr));
55     }
56
57     ~WeakPtrImpl()
58     {
59         WILL_DESTROY_WEAK_PTR_IMPL(m_ptr);
60     }
61
62     template<typename T> typename T::WeakValueType* get()
63     {
64         return static_cast<typename T::WeakValueType*>(m_ptr);
65     }
66
67     explicit operator bool() const { return m_ptr; }
68     void clear() { m_ptr = nullptr; }
69
70 private:
71     template<typename T> explicit WeakPtrImpl(T* ptr)
72         : m_ptr(static_cast<typename T::WeakValueType*>(ptr))
73     {
74         DID_CREATE_WEAK_PTR_IMPL(ptr);
75     }
76
77     void* m_ptr;
78 };
79
80 template<typename T>
81 class WeakPtr {
82     WTF_MAKE_FAST_ALLOCATED;
83 public:
84     WeakPtr() { }
85     WeakPtr(std::nullptr_t) { }
86     template<typename U> WeakPtr(const WeakPtr<U>&);
87     template<typename U> WeakPtr(WeakPtr<U>&&);
88
89     T* get() const { return m_impl ? static_cast<T*>(m_impl->get<T>()) : nullptr; }
90     explicit operator bool() const { return m_impl && *m_impl; }
91
92     WeakPtr& operator=(std::nullptr_t) { m_impl = nullptr; return *this; }
93     template<typename U> WeakPtr& operator=(const WeakPtr<U>&);
94     template<typename U> WeakPtr& operator=(WeakPtr<U>&&);
95
96     T* operator->() const { return get(); }
97     T& operator*() const { return *get(); }
98
99     void clear() { m_impl = nullptr; }
100
101 private:
102     explicit WeakPtr(Ref<WeakPtrImpl>&& ref) : m_impl(WTFMove(ref)) { }
103     template<typename> friend class WeakHashSet;
104     template<typename> friend class WeakPtr;
105     template<typename> friend class WeakPtrFactory;
106     template<typename U> friend WeakPtr<U> makeWeakPtr(U&);
107
108     RefPtr<WeakPtrImpl> m_impl;
109 };
110
111 // Note: you probably want to inherit from CanMakeWeakPtr rather than use this directly.
112 template<typename T>
113 class WeakPtrFactory {
114     WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>);
115     WTF_MAKE_FAST_ALLOCATED;
116 public:
117     WeakPtrFactory() = default;
118     ~WeakPtrFactory()
119     {
120         if (!m_impl)
121             return;
122         m_impl->clear();
123     }
124
125     WeakPtr<T> createWeakPtr(T& object) const
126     {
127         if (!m_impl)
128             m_impl = WeakPtrImpl::create(&object);
129
130         ASSERT(&object == m_impl->get<T>());
131         return WeakPtr<T>(makeRef(*m_impl));
132     }
133
134     WeakPtr<const T> createWeakPtr(const T& object) const
135     {
136         if (!m_impl)
137             m_impl = WeakPtrImpl::create(const_cast<T*>(&object));
138
139         ASSERT(&object == m_impl->get<T>());
140         return WeakPtr<T>(makeRef(*m_impl));
141     }
142
143     void revokeAll()
144     {
145         if (!m_impl)
146             return;
147
148         m_impl->clear();
149         m_impl = nullptr;
150     }
151
152 private:
153     template<typename> friend class WeakHashSet;
154
155     mutable RefPtr<WeakPtrImpl> m_impl;
156 };
157
158 template<typename T> class CanMakeWeakPtr {
159 public:
160     typedef T WeakValueType;
161
162     const WeakPtrFactory<T>& weakPtrFactory() const { return m_weakPtrFactory; }
163     WeakPtrFactory<T>& weakPtrFactory() { return m_weakPtrFactory; }
164
165 private:
166     WeakPtrFactory<T> m_weakPtrFactory;
167 };
168
169 template<typename T, typename U> inline WeakPtrImpl* weak_ptr_impl_cast(WeakPtrImpl* impl)
170 {
171     static_assert(std::is_same<typename T::WeakValueType, typename U::WeakValueType>::value, "Invalid weak pointer cast");
172     return impl;
173 }
174
175 template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(const WeakPtr<U>& o)
176     : m_impl(weak_ptr_impl_cast<T, U>(o.m_impl.get()))
177 {
178 }
179
180 template<typename T> template<typename U> inline WeakPtr<T>::WeakPtr(WeakPtr<U>&& o)
181     : m_impl(adoptRef(weak_ptr_impl_cast<T, U>(o.m_impl.leakRef())))
182 {
183 }
184
185 template<typename T> template<typename U> inline WeakPtr<T>& WeakPtr<T>::operator=(const WeakPtr<U>& o)
186 {
187     m_impl = weak_ptr_impl_cast<T, U>(o.m_impl.get());
188     return *this;
189 }
190
191 template<typename T> template<typename U> inline WeakPtr<T>& WeakPtr<T>::operator=(WeakPtr<U>&& o)
192 {
193     m_impl = adoptRef(weak_ptr_impl_cast<T, U>(o.m_impl.leakRef()));
194     return *this;
195 }
196
197 template<typename T> inline WeakPtr<T> makeWeakPtr(T& object)
198 {
199     return { object.weakPtrFactory().createWeakPtr(object) };
200 }
201
202 template<typename T> inline WeakPtr<T> makeWeakPtr(T* ptr)
203 {
204     if (!ptr)
205         return { };
206     return makeWeakPtr(*ptr);
207 }
208
209 template<typename T, typename U> inline bool operator==(const WeakPtr<T>& a, const WeakPtr<U>& b)
210 {
211     return a.get() == b.get();
212 }
213
214 template<typename T, typename U> inline bool operator==(const WeakPtr<T>& a, U* b)
215 {
216     return a.get() == b;
217 }
218
219 template<typename T, typename U> inline bool operator==(T* a, const WeakPtr<U>& b)
220 {
221     return a == b.get();
222 }
223
224 template<typename T, typename U> inline bool operator!=(const WeakPtr<T>& a, const WeakPtr<U>& b)
225 {
226     return a.get() != b.get();
227 }
228
229 template<typename T, typename U> inline bool operator!=(const WeakPtr<T>& a, U* b)
230 {
231     return a.get() != b;
232 }
233
234 template<typename T, typename U> inline bool operator!=(T* a, const WeakPtr<U>& b)
235 {
236     return a != b.get();
237 }
238
239 } // namespace WTF
240
241 using WTF::CanMakeWeakPtr;
242 using WTF::WeakPtr;
243 using WTF::WeakPtrFactory;
244 using WTF::makeWeakPtr;