#ifndef WebPrivatePtr_h
#define WebPrivatePtr_h
#include "WebCommon.h"
#if INSIDE_BLINK
namespace WebCore { template<typename T> class TreeShared; }
#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 {
typedef char TreeSharedType;
typedef struct {
char padding[8];
} NotTreeSharedType;
template<typename U> static TreeSharedType checkTreeShared(WebCore::TreeShared<U>*);
static NotTreeSharedType checkTreeShared(...);
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 =
sizeof(checkTreeShared(static_cast<T*>(0))) == sizeof(TreeSharedType) ? RefCountedLifetime :
!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:
PtrStorage();
PtrStorage(const PtrStorage&);
};
#endif
template <typename T>
class WebPrivatePtr {
public:
WebPrivatePtr() : m_storage(0) { }
~WebPrivatePtr()
{
BLINK_ASSERT(!m_storage);
}
bool isNull() const { return !m_storage; }
#if INSIDE_BLINK
template<typename U>
WebPrivatePtr(const U& ptr)
: m_storage(0)
{
storage().assign(ptr);
}
void reset() { storage().release(); }
WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other)
{
storage().assign(other.storage());
return *this;
}
template<typename U>
WebPrivatePtr<T>& operator=(const U& ptr)
{
storage().assign(ptr);
return *this;
}
T* get() const { return storage().get(); }
T& operator*() const
{
ASSERT(m_storage);
return *get();
}
T* operator->() const
{
ASSERT(m_storage);
return get();
}
#endif
private:
#if INSIDE_BLINK
PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_storage); }
const PtrStorage<T>& storage() const { return PtrStorage<T>::fromSlot(&m_storage); }
#endif
#if !INSIDE_BLINK
WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other);
#endif
WebPrivatePtr(const WebPrivatePtr<T>&);
void* m_storage;
};
}
#endif