#ifndef TreeShared_h
#define TreeShared_h
#include "public/platform/WebPrivatePtr.h"
#include "wtf/Assertions.h"
#include "wtf/MainThread.h"
#include "wtf/Noncopyable.h"
namespace WebCore {
#if SECURITY_ASSERT_ENABLED
template<typename NodeType> class TreeShared;
template<typename NodeType> void adopted(TreeShared<NodeType>*);
#endif
template<typename NodeType> class TreeShared : public NoBaseWillBeGarbageCollectedFinalized<NodeType> {
WTF_MAKE_NONCOPYABLE(TreeShared);
protected:
TreeShared()
: m_refCount(1)
#if ENABLE(OILPAN)
, m_keepAlive(adoptPtr(new Persistent<NodeType>(static_cast<NodeType*>(this))))
#endif
#if SECURITY_ASSERT_ENABLED
, m_deletionHasBegun(false)
#if ASSERT_ENABLED
, m_inRemovedLastRefFunction(false)
, m_adoptionIsRequired(true)
#endif
#endif
{
ASSERT(isMainThread());
}
~TreeShared()
{
ASSERT(isMainThread());
ASSERT(!m_refCount);
#if !ENABLE(OILPAN)
ASSERT_WITH_SECURITY_IMPLICATION(m_deletionHasBegun);
#else
ASSERT(!m_keepAlive);
#endif
ASSERT(!m_adoptionIsRequired);
}
public:
void ref()
{
ASSERT(isMainThread());
#if !ENABLE(OILPAN)
ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
ASSERT(!m_inRemovedLastRefFunction);
#endif
ASSERT(!m_adoptionIsRequired);
++m_refCount;
#if ENABLE(OILPAN)
if (!m_keepAlive)
m_keepAlive = adoptPtr(new Persistent<NodeType>(static_cast<NodeType*>(this)));
#endif
}
void deref()
{
ASSERT(isMainThread());
ASSERT(m_refCount > 0);
#if !ENABLE(OILPAN)
ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
ASSERT(!m_inRemovedLastRefFunction);
#endif
ASSERT(!m_adoptionIsRequired);
NodeType* thisNode = static_cast<NodeType*>(this);
if (!--m_refCount && !thisNode->hasTreeSharedParent()) {
#if !ASSERT_DISABLED
m_inRemovedLastRefFunction = true;
#endif
#if ENABLE(OILPAN)
clearKeepAlive();
#endif
thisNode->removedLastRef();
}
}
int refCount() const { return m_refCount; }
#if ENABLE(OILPAN)
void clearKeepAlive()
{
ASSERT(m_keepAlive);
m_keepAlive = nullptr;
}
#endif
private:
int m_refCount;
#if ENABLE(OILPAN)
OwnPtr<Persistent<NodeType> > m_keepAlive;
#endif
#if SECURITY_ASSERT_ENABLED
public:
bool m_deletionHasBegun;
#if ASSERT_ENABLED
bool m_inRemovedLastRefFunction;
private:
friend void adopted<>(TreeShared<NodeType>*);
bool m_adoptionIsRequired;
#endif
#endif
};
#if SECURITY_ASSERT_ENABLED
template<typename NodeType> inline void adopted(TreeShared<NodeType>* object)
{
if (!object)
return;
ASSERT_WITH_SECURITY_IMPLICATION(!object->m_deletionHasBegun);
#if !ASSERT_DISABLED
ASSERT(!object->m_inRemovedLastRefFunction);
object->m_adoptionIsRequired = false;
#endif
}
#endif
}
#endif