Index: public/platform/WebPrivatePtr.h |
diff --git a/public/platform/WebPrivatePtr.h b/public/platform/WebPrivatePtr.h |
index a0b57c9a41b70178e273615194888766576cf7c5..b914710fc0781697fd6d3047b94b77ca3531dbaa 100644 |
--- a/public/platform/WebPrivatePtr.h |
+++ b/public/platform/WebPrivatePtr.h |
@@ -34,11 +34,128 @@ |
#include "WebCommon.h" |
#if INSIDE_BLINK |
+#include "heap/Handle.h" |
#include "wtf/PassRefPtr.h" |
+#include "wtf/TypeTraits.h" |
#endif |
namespace blink { |
+#if INSIDE_BLINK |
+enum LifetimeManagementType { |
+ RefCountedLifetime, |
+ GarbageCollectedLifetime, |
+ RefCountedGarbageCollectedLifetime |
+}; |
+ |
+template<typename T> |
+class LifetimeOf { |
+ static const bool isGarbageCollected = WTF::IsSubclassOfTemplate<T, WebCore::GarbageCollected>::value; |
+ static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<T, WebCore::RefCountedGarbageCollected>::value; |
+public: |
+ static const LifetimeManagementType value = |
+ !isGarbageCollected ? RefCountedLifetime : |
+ isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime; |
+}; |
+ |
+template<typename T, LifetimeManagementType lifetime> |
+class PtrStorageImpl; |
+ |
+template<typename T> |
+class PtrStorageImpl<T, RefCountedLifetime> { |
+public: |
+ typedef PassRefPtr<T> BlinkPtrType; |
+ |
+ void assign(const BlinkPtrType& val) |
+ { |
+ release(); |
+ m_ptr = val.leakRef(); |
+ } |
+ |
+ void assign(const PtrStorageImpl& other) |
+ { |
+ release(); |
+ T* val = other.get(); |
+ if (val) |
+ val->ref(); |
+ m_ptr = val; |
+ } |
+ |
+ T* get() const { return m_ptr; } |
+ |
+ void release() |
+ { |
+ if (m_ptr) |
+ m_ptr->deref(); |
+ m_ptr = 0; |
+ } |
+ |
+private: |
+ T* m_ptr; |
+}; |
+ |
+template<typename T> |
+class PtrStorageImpl<T, GarbageCollectedLifetime> { |
+public: |
+ void assign(const RawPtr<T>& val) |
+ { |
+ if (!val) { |
+ release(); |
+ return; |
+ } |
+ |
+ if (!m_handle) |
+ m_handle = new WebCore::Persistent<T>(); |
+ |
+ (*m_handle) = val; |
+ } |
+ |
+ void assign(T* ptr) { assign(RawPtr<T>(ptr)); } |
+ |
+ void assign(const PtrStorageImpl& other) { assign(other.get()); } |
+ |
+ T* get() const { return m_handle ? m_handle->get() : 0; } |
+ |
+ void release() |
+ { |
+ delete m_handle; |
+ m_handle = 0; |
+ } |
+ |
+private: |
+ WebCore::Persistent<T>* m_handle; |
+}; |
+ |
+template<typename T> |
+class PtrStorageImpl<T, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, GarbageCollectedLifetime> { |
+public: |
+ void assign(const PassRefPtr<T>& val) { assign(RawPtr<T>(val.get())); } |
+ |
+ void assign(const PtrStorageImpl& other) { assign(RawPtr<T>(other.get())); } |
+}; |
+ |
+template<typename T> |
+class PtrStorage : public PtrStorageImpl<T, LifetimeOf<T>::value> { |
+public: |
+ static PtrStorage& fromSlot(void** slot) |
+ { |
+ COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size); |
+ return *reinterpret_cast<PtrStorage*>(slot); |
+ } |
+ |
+ static const PtrStorage& fromSlot(void* const* slot) |
+ { |
+ COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size); |
+ return *reinterpret_cast<const PtrStorage*>(slot); |
+ } |
+ |
+private: |
+ // Prevent construction via normal means. |
+ PtrStorage(); |
+ PtrStorage(const PtrStorage&); |
+}; |
+#endif |
+ |
// This class is an implementation detail of the Blink API. It exists to help |
// simplify the implementation of Blink interfaces that merely wrap a reference |
// counted WebCore class. |
@@ -78,66 +195,63 @@ namespace blink { |
template <typename T> |
class WebPrivatePtr { |
public: |
- WebPrivatePtr() : m_ptr(0) { } |
+ WebPrivatePtr() : m_storage(0) { } |
~WebPrivatePtr() |
{ |
// We don't destruct the object pointed by m_ptr here because we don't |
// want to expose destructors of core classes to embedders. We should |
// call reset() manually in destructors of classes with WebPrivatePtr |
// members. |
- BLINK_ASSERT(!m_ptr); |
+ BLINK_ASSERT(!m_storage); |
} |
- bool isNull() const { return !m_ptr; } |
+ bool isNull() const { return !m_storage; } |
#if INSIDE_BLINK |
- WebPrivatePtr(const PassRefPtr<T>& prp) |
- : m_ptr(prp.leakRef()) |
+ template<typename U> |
+ WebPrivatePtr(const U& ptr) |
+ : m_storage(0) |
{ |
+ storage().assign(ptr); |
} |
- void reset() |
- { |
- assign(0); |
- } |
+ void reset() { storage().release(); } |
WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other) |
{ |
- T* p = other.m_ptr; |
- if (p) |
- p->ref(); |
- assign(p); |
+ storage().assign(other.storage()); |
return *this; |
} |
- WebPrivatePtr<T>& operator=(const PassRefPtr<T>& prp) |
+ WebPrivatePtr<T>& operator=(std::nullptr_t) |
{ |
- assign(prp.leakRef()); |
+ reset(); |
return *this; |
} |
- T* get() const |
+ template<typename U> |
+ WebPrivatePtr<T>& operator=(const U& ptr) |
{ |
- return m_ptr; |
+ storage().assign(ptr); |
+ return *this; |
} |
+ T* get() const { return storage().get(); } |
+ |
T* operator->() const |
{ |
- ASSERT(m_ptr); |
- return m_ptr; |
+ ASSERT(m_storage); |
+ return get(); |
} |
#endif |
private: |
#if INSIDE_BLINK |
- void assign(T* p) |
- { |
- // p is already ref'd for us by the caller |
- if (m_ptr) |
- m_ptr->deref(); |
- m_ptr = p; |
- } |
-#else |
+ PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_storage); } |
+ const PtrStorage<T>& storage() const { return PtrStorage<T>::fromSlot(&m_storage); } |
+#endif |
+ |
+#if !INSIDE_BLINK |
// Disable the assignment operator; we define it above for when |
// INSIDE_BLINK is set, but we need to make sure that it is not |
// used outside there; the compiler-provided version won't handle reference |
@@ -148,7 +262,7 @@ private: |
// should implement their copy constructor using assign(). |
WebPrivatePtr(const WebPrivatePtr<T>&); |
- T* m_ptr; |
+ void* m_storage; |
}; |
} // namespace blink |