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 72 void assign(const BlinkPtrType& val) 73 { 74 release(); 75 m_ptr = val.leakRef(); 76 } 77 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 87 T* get() const { return m_ptr; } 88 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: 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 116 void assign(T* ptr) { assign(RawPtr<T>(ptr)); } 117 template<typename U> void assign(const RawPtr<U>& val) { assign(RawPtr<T>(val)); } 118 119 void assign(const PtrStorageImpl& other) { assign(other.get()); } 120 121 T* get() const { return m_handle ? m_handle->get() : 0; } 122 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: 136 void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); } 137 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: 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 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: 203 WebPrivatePtr() : m_storage(0) { } 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 213 bool isNull() const { return !m_storage; } 214 215 #if INSIDE_BLINK 216 template<typename U> 217 WebPrivatePtr(const U& ptr) 218 : m_storage(0) 219 { 220 storage().assign(ptr); 221 } 222 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 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 255 PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_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