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