Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / public / platform / WebPrivatePtr.h
blobb4b9a2887859e4d44c3788fcadc314219ac55d1d
1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef WebPrivatePtr_h
32 #define WebPrivatePtr_h
34 #include "WebCommon.h"
36 #if INSIDE_BLINK
37 #include "platform/heap/Handle.h"
38 #include "wtf/PassRefPtr.h"
39 #include "wtf/TypeTraits.h"
40 #endif
42 namespace WTF {
43 template<class T> class ThreadSafeRefCounted;
46 namespace blink {
48 // By default, the destruction of a WebPrivatePtr<> must happen on the same
49 // thread that created it, but can optionally be allowed to happen on
50 // another thread.
51 enum WebPrivatePtrDestruction {
52 WebPrivatePtrDestructionSameThread,
53 WebPrivatePtrDestructionCrossThread,
56 #if INSIDE_BLINK
57 enum LifetimeManagementType {
58 RefCountedLifetime,
59 GarbageCollectedLifetime,
60 RefCountedGarbageCollectedLifetime
63 template<typename T>
64 class LifetimeOf {
65 static const bool isGarbageCollected = WTF::IsSubclassOfTemplate<T, GarbageCollected>::value || IsGarbageCollectedMixin<T>::value;
66 static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<T, RefCountedGarbageCollected>::value;
67 public:
68 static const LifetimeManagementType value =
69 !isGarbageCollected ? RefCountedLifetime :
70 isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime;
73 template<typename T, WebPrivatePtrDestruction crossThreadDestruction, LifetimeManagementType lifetime>
74 class PtrStorageImpl;
76 template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
77 class PtrStorageImpl<T, crossThreadDestruction, RefCountedLifetime> {
78 public:
79 typedef PassRefPtr<T> BlinkPtrType;
81 void assign(const BlinkPtrType& val)
83 static_assert(crossThreadDestruction == WebPrivatePtrDestructionSameThread || WTF::IsSubclassOfTemplate<T, WTF::ThreadSafeRefCounted>::value, "Cross thread destructible class must derive from ThreadSafeRefCounted<>");
84 release();
85 m_ptr = val.leakRef();
88 void assign(const PtrStorageImpl& other)
90 release();
91 T* val = other.get();
92 WTF::refIfNotNull(val);
93 m_ptr = val;
96 void moveFrom(PtrStorageImpl& other)
98 release();
99 m_ptr = other.m_ptr;
100 other.m_ptr = 0;
103 T* get() const { return m_ptr; }
105 void release()
107 WTF::derefIfNotNull(m_ptr);
108 m_ptr = 0;
111 private:
112 T* m_ptr;
115 template <typename T, WebPrivatePtrDestruction>
116 struct WebPrivatePtrPersistentStorageType {
117 public:
118 using Type = Persistent<T>;
121 template <typename T>
122 struct WebPrivatePtrPersistentStorageType<T, WebPrivatePtrDestructionCrossThread> {
123 public:
124 using Type = CrossThreadPersistent<T>;
127 template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
128 class PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime> {
129 public:
130 void assign(const RawPtr<T>& val)
132 if (!val) {
133 release();
134 return;
137 if (!m_handle)
138 m_handle = new (typename WebPrivatePtrPersistentStorageType<T, crossThreadDestruction>::Type)();
140 (*m_handle) = val;
143 void assign(T* ptr) { assign(RawPtr<T>(ptr)); }
144 template<typename U> void assign(const RawPtr<U>& val) { assign(RawPtr<T>(val)); }
146 void assign(const PtrStorageImpl& other) { assign(other.get()); }
148 void moveFrom(PtrStorageImpl& other)
150 release();
151 m_handle = other.m_handle;
152 other.m_handle = 0;
155 T* get() const { return m_handle ? m_handle->get() : 0; }
157 void release()
159 delete m_handle;
160 m_handle = 0;
163 private:
164 typename WebPrivatePtrPersistentStorageType<T, crossThreadDestruction>::Type* m_handle;
167 template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
168 class PtrStorageImpl<T, crossThreadDestruction, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime> {
169 public:
170 void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime>::assign(val.get()); }
172 void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime>::assign(other.get()); }
175 template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
176 class PtrStorage : public PtrStorageImpl<T, crossThreadDestruction, LifetimeOf<T>::value> {
177 public:
178 static PtrStorage& fromSlot(void** slot)
180 static_assert(sizeof(PtrStorage) == sizeof(void*), "PtrStorage must be the size of a pointer");
181 return *reinterpret_cast<PtrStorage*>(slot);
184 static const PtrStorage& fromSlot(void* const* slot)
186 static_assert(sizeof(PtrStorage) == sizeof(void*), "PtrStorage must be the size of a pointer");
187 return *reinterpret_cast<const PtrStorage*>(slot);
190 private:
191 // Prevent construction via normal means.
192 PtrStorage();
193 PtrStorage(const PtrStorage&);
195 #endif
197 // This class is an implementation detail of the Blink API. It exists to help
198 // simplify the implementation of Blink interfaces that merely wrap a reference
199 // counted WebCore class.
201 // A typical implementation of a class which uses WebPrivatePtr might look like
202 // this:
203 // class WebFoo {
204 // public:
205 // BLINK_EXPORT ~WebFoo();
206 // WebFoo() { }
207 // WebFoo(const WebFoo& other) { assign(other); }
208 // WebFoo& operator=(const WebFoo& other)
209 // {
210 // assign(other);
211 // return *this;
212 // }
213 // BLINK_EXPORT void assign(const WebFoo&); // Implemented in the body.
215 // // Methods that are exposed to Chromium and which are specific to
216 // // WebFoo go here.
217 // BLINK_EXPORT doWebFooThing();
219 // // Methods that are used only by other Blink classes should only be
220 // // declared when INSIDE_BLINK is set.
221 // #if INSIDE_BLINK
222 // WebFoo(const WTF::PassRefPtr<Foo>&);
223 // #endif
225 // private:
226 // WebPrivatePtr<Foo> m_private;
227 // };
229 // // WebFoo.cpp
230 // WebFoo::~WebFoo() { m_private.reset(); }
231 // void WebFoo::assign(const WebFoo& other) { ... }
233 template <typename T, WebPrivatePtrDestruction crossThreadDestruction = WebPrivatePtrDestructionSameThread>
234 class WebPrivatePtr {
235 public:
236 WebPrivatePtr() : m_storage(0) { }
237 ~WebPrivatePtr()
239 // We don't destruct the object pointed by m_ptr here because we don't
240 // want to expose destructors of core classes to embedders. We should
241 // call reset() manually in destructors of classes with WebPrivatePtr
242 // members.
243 BLINK_ASSERT(!m_storage);
246 bool isNull() const { return !m_storage; }
248 #if INSIDE_BLINK
249 template<typename U>
250 WebPrivatePtr(const U& ptr)
251 : m_storage(0)
253 storage().assign(ptr);
256 void reset() { storage().release(); }
258 WebPrivatePtr& operator=(const WebPrivatePtr& other)
260 storage().assign(other.storage());
261 return *this;
264 void moveFrom(WebPrivatePtr& other)
266 storage().moveFrom(other.storage());
267 return;
270 template<typename U>
271 WebPrivatePtr& operator=(const U& ptr)
273 storage().assign(ptr);
274 return *this;
277 T* get() const { return storage().get(); }
279 T& operator*() const
281 ASSERT(m_storage);
282 return *get();
285 T* operator->() const
287 ASSERT(m_storage);
288 return get();
290 #endif
292 private:
293 #if INSIDE_BLINK
294 PtrStorage<T, crossThreadDestruction>& storage() { return PtrStorage<T, crossThreadDestruction>::fromSlot(&m_storage); }
295 const PtrStorage<T, crossThreadDestruction>& storage() const { return PtrStorage<T, crossThreadDestruction>::fromSlot(&m_storage); }
296 #endif
298 #if !INSIDE_BLINK
299 // Disable the assignment operator; we define it above for when
300 // INSIDE_BLINK is set, but we need to make sure that it is not
301 // used outside there; the compiler-provided version won't handle reference
302 // counting properly.
303 WebPrivatePtr& operator=(const WebPrivatePtr& other);
304 #endif
305 // Disable the copy constructor; classes that contain a WebPrivatePtr
306 // should implement their copy constructor using assign().
307 WebPrivatePtr(const WebPrivatePtr&);
309 void* m_storage;
312 } // namespace blink
314 #endif