'RefPtr'에 해당되는 글 1건

  1. 2009.12.11 WebKit Smart Pointer (RefPtr, PassRefPtr)

WebKit Smart Pointer (RefPtr, PassRefPtr)

CS/C/C++ 2009. 12. 11. 05:52
참조 :
1. http://webkit.org/coding/RefPtr.html
2. WebKit Source Code

RefPtr
Simple smart pointer.

생성자 및 소멸자
template <typename T>
RefPtr<T>::RefPtr() : m_ptr(0)
{ }

template <typename T>
RefPtr<T>::RefPtr(T* ptr) : m_ptr(ptr)
{
    if (ptr) ptr->ref();
}

template <typename T>
RefPtr<T>::~RefPtr()
{
    if (T* ptr = m_ptr) ptr->deref();
}

복사 생성자
template <typename T>
RefPtr<T>::RefPtr(const RefPtr& o) : m_ptr(o.m_ptr)
{
    if (T* ptr = m_ptr) ptr->ref();
}

대입 연산자
template <typename T> inline
RefPtr<T>& RefPtr<T>::operator=(T* optr)
{
    if (optr)
        optr->ref();
    T* ptr = m_ptr;
    m_ptr = optr;
    if (ptr)
        ptr->deref();
    return *this;
}

template <typename T> inline
RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
{
    T* optr = o.get();
    if (optr)
        optr->ref();
    T* ptr = m_ptr;
    m_ptr = optr;
    if (ptr)
        ptr->deref();
    return *this;
}

template <typename T> inline
RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
{
    T* ptr = m_ptr;
    m_ptr = o.releaseRef();
    if (ptr)
        ptr->deref();
    return *this;
}

사용 예
// example, not preferred style
class Document
{
    // ...
    RefPtr<Title> m_title;
}

void Document::setTitle(Title* title)
{
    m_title = title;
}

// example, not preferred style
RefPtr<Node> createSpecialNode()
{
    RefPtr<Node> a = new Node;
    a->setSpecial(true);
    return a;
}

RefPtr<Node> b = createSpecialNode();



PassRefPtr
전달시 Ownership을 포기한다.
Recommended only for function argument and result types, copying arguments into RefPtr local variables.

void derefIfNotNull(T* ptr)
{
    if (UNLIKELY(ptr != 0))
        ptr->deref();
}

template <typename T>
T* PassRefPtr<T>::releaseRef() const
{
    T* tmp = m_ptr;
    m_ptr = 0;
    return tmp;
}

생성자 및 소멸자
template <typename T>
PassRefPtr<T>::PassRefPtr() : m_ptr(0)
{ }


template <typename T>
PassRefPtr<T>::PassRefPtr(T* ptr) : m_ptr(ptr)
{
    if (ptr) ptr->ref();
}


template <typename T>
PassRefPtr<T>::~PassRefPtr()
{
    derefIfNotNull<T>(m_ptr);
}


복사 생성자
template <typename T>
PassRefPtr<T>::PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef())
{}


대입 연산자
template <typename T> inline
PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
{
    if (optr)
        optr->ref();
    T* ptr = m_ptr;
    m_ptr = optr;
    if (ptr)
        ptr->deref();
    return *this;
}

template <typename T> inline
PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
{
    T* ptr = m_ptr;
    m_ptr = ref.releaseRef();
    if (ptr)
        ptr->deref();
    return *this;
}


사용 예
// example, not preferred style
PassRefPtr<Node> createSpecialNode()
{
    PassRefPtr<Node> a = new Node;
    a->setSpecial(true);
    return a;
}

RefPtr<Node> b = createSpecialNode();

WebKit에서는 모든 경우에 RefPtr을 사용하기를 권장한다. 따라서 위의 경우처럼 ownership을 전달하고자 하는 경우
// example, assuming new Node starts with reference count 0
PassRefPtr<Node> createSpecialNode()
{
    RefPtr<Node> a = new Node;
    a->setSpecial(true);
    return a.release();
}

RefPtr<Node> b = createSpecialNode();




adoptRef
Reference count의 조작 없이 생성된 객체를 전달할 수 있게 한다. PassRefPtr의 friend로 되어있다.

template <typename T>
PassRefPtr<T>::PassRefPtr(T* ptr, bool) : m_ptr(ptr)
{ }

template <typename T> inline PassRefPtr<T> adoptRef(T* p)
{
    return PassRefPtr<T>(p, true);
}

사용 예
// preferred style
PassRefPtr<Node> Node::create()
{
    return adoptRef(new Node);
}
RefPtr<Node> e = Node::create();

// preferred style
PassRefPtr<Node> createSpecialNode()
{
    RefPtr<Node> a = Node::create();
    a->setCreated(true);
    return a.release();
}
RefPtr<Node> b = createSpecialNode();



OwnPtr, PassOwnPtr
RefPtr, PassRefPtr은 RefCounted에서 상속받은 클래스에만 적용할 수 있는 반면, OwnPtr, PassOwnPtr은 pointer type이나 pointed-to type을 취할 수 있다.
복사 생성자를 보면 인자로 std::auto_ptr을 받는데... 그렇다면 결국 패싱할때 소유권을 넘긴다는 말인데... 흠... 음... 흠... 좀더 살펴 봐야 겠다.

template <typename T>
struct RemovePointer {
    typedef T Type;
};

template <typename T>
struct RemovePointer<T*> {
    typedef T Type;
};

template <typename T> class OwnPtr : public Noncopyable
{
public:
    typedef typename RemovePointer<T>::Type ValueType;
    typedef ValueType* PtrType;   
    // ...

private:
    PtrType m_ptr;
};

생성자 및 소멸자
template typename<T> explicit
OwnPtr<T>::OwnPtr(PtrType ptr = 0) : m_ptr(ptr)
{ }

template typename<T>
OwnPtr<T>::~OwnPtr()
{
    deleteOwnedPtr(m_ptr);
}

복사 생성자
template typename<T>
OwnPtr<T>::OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release())
{ }

대입 연산자
template <typename T> inline
OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)

{
    T* ptr = m_ptr;
    m_ptr = o.release();
    if (ptr)
        deleteOwnedPtr(ptr);
    return *this;
}

: