Chromium Code Reviews| Index: public/platform/WebPrivatePtr.h |
| diff --git a/public/platform/WebPrivatePtr.h b/public/platform/WebPrivatePtr.h |
| index a0b57c9a41b70178e273615194888766576cf7c5..4b3da1c3400713d15b662e19784df23ce6f12de6 100644 |
| --- a/public/platform/WebPrivatePtr.h |
| +++ b/public/platform/WebPrivatePtr.h |
| @@ -34,11 +34,129 @@ |
| #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) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); } |
| + |
| + void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(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 +196,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&) |
|
jamesr
2014/02/18 22:18:53
NAK on this - we can't expose std::nullptr_t throu
jamesr
2014/02/18 22:20:30
Ah - I missed that this was in the INSIDE_BLINK se
sof
2014/02/19 06:11:44
It will go away once https://codereview.chromium.o
|
| { |
| - 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 +263,7 @@ private: |
| // should implement their copy constructor using assign(). |
| WebPrivatePtr(const WebPrivatePtr<T>&); |
| - T* m_ptr; |
| + void* m_storage; |
| }; |
| } // namespace blink |