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 42namespace blink { 43 44#if INSIDE_BLINK 45enum LifetimeManagementType { 46 RefCountedLifetime, 47 GarbageCollectedLifetime, 48 RefCountedGarbageCollectedLifetime 49}; 50 51template<typename T> 52class LifetimeOf { 53 static const bool isGarbageCollected = WTF::IsSubclassOfTemplate<T, GarbageCollected>::value; 54 static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<T, RefCountedGarbageCollected>::value; 55public: 56 static const LifetimeManagementType value = 57 !isGarbageCollected ? RefCountedLifetime : 58 isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime; 59}; 60 61template<typename T, LifetimeManagementType lifetime> 62class PtrStorageImpl; 63 64template<typename T> 65class PtrStorageImpl<T, RefCountedLifetime> { 66public: 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 91private: 92 T* m_ptr; 93}; 94 95template<typename T> 96class PtrStorageImpl<T, GarbageCollectedLifetime> { 97public: 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 124private: 125 Persistent<T>* m_handle; 126}; 127 128template<typename T> 129class PtrStorageImpl<T, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, GarbageCollectedLifetime> { 130public: 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 136template<typename T> 137class PtrStorage : public PtrStorageImpl<T, LifetimeOf<T>::value> { 138public: 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 151private: 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// 195template <typename T> 196class WebPrivatePtr { 197public: 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 248private: 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