• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
17  *
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.
29  */
30 
31 #ifndef WebPrivatePtr_h
32 #define WebPrivatePtr_h
33 
34 #include "WebCommon.h"
35 
36 #if INSIDE_BLINK
37 
38 namespace WebCore { template<typename T> class TreeShared; }
39 
40 #include "platform/heap/Handle.h"
41 #include "wtf/PassRefPtr.h"
42 #include "wtf/TypeTraits.h"
43 #endif
44 
45 namespace blink {
46 
47 #if INSIDE_BLINK
48 enum LifetimeManagementType {
49     RefCountedLifetime,
50     GarbageCollectedLifetime,
51     RefCountedGarbageCollectedLifetime
52 };
53 
54 template<typename T>
55 class LifetimeOf {
56     static const bool isGarbageCollected = WTF::IsSubclassOfTemplate<T, WebCore::GarbageCollected>::value;
57     static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<T, WebCore::RefCountedGarbageCollected>::value;
58 public:
59     static const LifetimeManagementType value =
60         !isGarbageCollected ? RefCountedLifetime :
61         isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime;
62 };
63 
64 template<typename T, LifetimeManagementType lifetime>
65 class PtrStorageImpl;
66 
67 template<typename T>
68 class PtrStorageImpl<T, RefCountedLifetime> {
69 public:
70     typedef PassRefPtr<T> BlinkPtrType;
71 
assign(const BlinkPtrType & val)72     void assign(const BlinkPtrType& val)
73     {
74         release();
75         m_ptr = val.leakRef();
76     }
77 
assign(const PtrStorageImpl & other)78     void assign(const PtrStorageImpl& other)
79     {
80         release();
81         T* val = other.get();
82         if (val)
83             val->ref();
84         m_ptr = val;
85     }
86 
get()87     T* get() const { return m_ptr; }
88 
release()89     void release()
90     {
91         if (m_ptr)
92             m_ptr->deref();
93         m_ptr = 0;
94     }
95 
96 private:
97     T* m_ptr;
98 };
99 
100 template<typename T>
101 class PtrStorageImpl<T, GarbageCollectedLifetime> {
102 public:
assign(const RawPtr<T> & val)103     void assign(const RawPtr<T>& val)
104     {
105         if (!val) {
106             release();
107             return;
108         }
109 
110         if (!m_handle)
111             m_handle = new WebCore::Persistent<T>();
112 
113         (*m_handle) = val;
114     }
115 
assign(T * ptr)116     void assign(T* ptr) { assign(RawPtr<T>(ptr)); }
assign(const RawPtr<U> & val)117     template<typename U> void assign(const RawPtr<U>& val) { assign(RawPtr<T>(val)); }
118 
assign(const PtrStorageImpl & other)119     void assign(const PtrStorageImpl& other) { assign(other.get()); }
120 
get()121     T* get() const { return m_handle ? m_handle->get() : 0; }
122 
release()123     void release()
124     {
125         delete m_handle;
126         m_handle = 0;
127     }
128 
129 private:
130     WebCore::Persistent<T>* m_handle;
131 };
132 
133 template<typename T>
134 class PtrStorageImpl<T, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, GarbageCollectedLifetime> {
135 public:
assign(const PassRefPtrWillBeRawPtr<T> & val)136     void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); }
137 
assign(const PtrStorageImpl & other)138     void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(other.get()); }
139 };
140 
141 template<typename T>
142 class PtrStorage : public PtrStorageImpl<T, LifetimeOf<T>::value> {
143 public:
fromSlot(void ** slot)144     static PtrStorage& fromSlot(void** slot)
145     {
146         COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size);
147         return *reinterpret_cast<PtrStorage*>(slot);
148     }
149 
fromSlot(void * const * slot)150     static const PtrStorage& fromSlot(void* const* slot)
151     {
152         COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size);
153         return *reinterpret_cast<const PtrStorage*>(slot);
154     }
155 
156 private:
157     // Prevent construction via normal means.
158     PtrStorage();
159     PtrStorage(const PtrStorage&);
160 };
161 #endif
162 
163 
164 // This class is an implementation detail of the Blink API. It exists to help
165 // simplify the implementation of Blink interfaces that merely wrap a reference
166 // counted WebCore class.
167 //
168 // A typical implementation of a class which uses WebPrivatePtr might look like
169 // this:
170 //    class WebFoo {
171 //    public:
172 //        BLINK_EXPORT ~WebFoo();
173 //        WebFoo() { }
174 //        WebFoo(const WebFoo& other) { assign(other); }
175 //        WebFoo& operator=(const WebFoo& other)
176 //        {
177 //            assign(other);
178 //            return *this;
179 //        }
180 //        BLINK_EXPORT void assign(const WebFoo&);  // Implemented in the body.
181 //
182 //        // Methods that are exposed to Chromium and which are specific to
183 //        // WebFoo go here.
184 //        BLINK_EXPORT doWebFooThing();
185 //
186 //        // Methods that are used only by other Blink classes should only be
187 //        // declared when INSIDE_BLINK is set.
188 //    #if INSIDE_BLINK
189 //        WebFoo(const WTF::PassRefPtr<WebCore::Foo>&);
190 //    #endif
191 //
192 //    private:
193 //        WebPrivatePtr<WebCore::Foo> m_private;
194 //    };
195 //
196 //    // WebFoo.cpp
197 //    WebFoo::~WebFoo() { m_private.reset(); }
198 //    void WebFoo::assign(const WebFoo& other) { ... }
199 //
200 template <typename T>
201 class WebPrivatePtr {
202 public:
WebPrivatePtr()203     WebPrivatePtr() : m_storage(0) { }
~WebPrivatePtr()204     ~WebPrivatePtr()
205     {
206         // We don't destruct the object pointed by m_ptr here because we don't
207         // want to expose destructors of core classes to embedders. We should
208         // call reset() manually in destructors of classes with WebPrivatePtr
209         // members.
210         BLINK_ASSERT(!m_storage);
211     }
212 
isNull()213     bool isNull() const { return !m_storage; }
214 
215 #if INSIDE_BLINK
216     template<typename U>
WebPrivatePtr(const U & ptr)217     WebPrivatePtr(const U& ptr)
218         : m_storage(0)
219     {
220         storage().assign(ptr);
221     }
222 
reset()223     void reset() { storage().release(); }
224 
225     WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other)
226     {
227         storage().assign(other.storage());
228         return *this;
229     }
230 
231     template<typename U>
232     WebPrivatePtr<T>& operator=(const U& ptr)
233     {
234         storage().assign(ptr);
235         return *this;
236     }
237 
get()238     T* get() const { return storage().get(); }
239 
240     T& operator*() const
241     {
242         ASSERT(m_storage);
243         return *get();
244     }
245 
246     T* operator->() const
247     {
248         ASSERT(m_storage);
249         return get();
250     }
251 #endif
252 
253 private:
254 #if INSIDE_BLINK
storage()255     PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_storage); }
storage()256     const PtrStorage<T>& storage() const { return PtrStorage<T>::fromSlot(&m_storage); }
257 #endif
258 
259 #if !INSIDE_BLINK
260     // Disable the assignment operator; we define it above for when
261     // INSIDE_BLINK is set, but we need to make sure that it is not
262     // used outside there; the compiler-provided version won't handle reference
263     // counting properly.
264     WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other);
265 #endif
266     // Disable the copy constructor; classes that contain a WebPrivatePtr
267     // should implement their copy constructor using assign().
268     WebPrivatePtr(const WebPrivatePtr<T>&);
269 
270     void* m_storage;
271 };
272 
273 } // namespace blink
274 
275 #endif
276