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 69 void assign(const BlinkPtrType& val) 70 { 71 release(); 72 m_ptr = val.leakRef(); 73 } 74 75 void assign(const PtrStorageImpl& other) 76 { 77 release(); 78 T* val = other.get(); 79 WTF::refIfNotNull(val); 80 m_ptr = val; 81 } 82 83 T* get() const { return m_ptr; } 84 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: 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 111 void assign(T* ptr) { assign(RawPtr<T>(ptr)); } 112 template<typename U> void assign(const RawPtr<U>& val) { assign(RawPtr<T>(val)); } 113 114 void assign(const PtrStorageImpl& other) { assign(other.get()); } 115 116 T* get() const { return m_handle ? m_handle->get() : 0; } 117 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: 131 void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); } 132 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: 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 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: 198 WebPrivatePtr() : m_storage(0) { } 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 208 bool isNull() const { return !m_storage; } 209 210 #if INSIDE_BLINK 211 template<typename U> 212 WebPrivatePtr(const U& ptr) 213 : m_storage(0) 214 { 215 storage().assign(ptr); 216 } 217 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 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 250 PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_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