WebKit의 RefPtr 및 PassRefPtr

4217 단어
다음으로: 웹키 기술 번역 시리즈 (2): RefPtr 및PassRefPtr 기초
텍스트 링크:http://webkit.org/coding/RefPtr.html

역사.


WebKit의 많은 대상은 인용계수(reference counted)인데 사용하는 모델은 ref와deref 구성원 함수를 가지고 인용계수를 증가하고 감소하는 것이다.모든ref 호출은deref와 일치해야 합니다.인용 계수 값이 1인 대상에서deref 방법을 호출할 때 대상은 삭제됩니다.WebKit의 많은 클래스는 RefCounted 클래스 템플릿을 상속하여 이 모드를 적용합니다.
2005년으로 거슬러 올라가면, 우리는ref와deref를 잘못 호출해서 발생한 메모리 유출, 특히 HTML로 편집된 코드가 많이 존재한다는 것을 발견했다.
우리는 지능 지침을 사용하여 이 문제를 줄이기를 바란다.그러나 초기 실험에서는 스마트 포인터가 추가 인용 계수 처리를 해 성능에 영향을 미친다는 것이 밝혀졌다.예를 들어 한 함수에 스마트 포인터의 매개 변수가 있고 이 포인터를 반환값으로 되돌려줍니다. 이 매개 변수만 전송하고 이 값을 되돌려주면 인용 계수 값을 2~4회 증가하고 감소합니다. 왜냐하면 대상이 스마트 포인터에서 다른 위로 이동하기 때문입니다.따라서 우리는 스마트 포인터를 사용하는 동시에 인용 계수 변동(churn)을 피할 수 있는 방법을 찾았다.
C++ 표준 클래스 템플릿에서 autoptr는 영감을 얻었습니다. 이 대상들은 하나의 모델을 실현했습니다. 값은 귀속 관계 이동(transfer of ownership)입니다. auto 에서ptr는 다른 값으로 부여하고 공헌치는 0이 됩니다.(When you assign from one auto_ptr to another, the donor becomes 0.)
Maciej Stachowiak은 한 쌍의 클래스 템플릿, RefPtr와PassRefPtr를 설계하여 이 모델을 실현하여WebKit에서 짜증나는 인용 계수 문제를 해결했다.

원래 포인터(Raw pointers)


RefPtr 클래스 템플릿과 같은 스마트 포인터를 논의할 때, 보통 원시 포인터(raw pointer)를 사용하여 C++ 언어에 내장된 포인터 유형을 가리킨다.다음은 원본 포인터(raw pointer)를 사용하는 클래식 설정 함수입니다.
// example, not preferred style

class Document {
...
Title* m_title;
}
Document::Document()
: m_title(0)
{
}
Document::~Document()
{
if (m_title)
m_title->deref();
}
void Document::setTitle(Title* title)
{
if (title)
title->ref();
if (m_title)
m_title->deref();
m_title = title;
}

 


RefPtr


RefPtr는 간단한 스마트 포인터 종류로, 리셋 값 (incoming value) 은ref를 호출하고, 리셋 값 (outgoing value) 은deref를 호출합니다.RefPtr는 ref와deref 구성원 함수가 있는 모든 객체에 사용할 수 있습니다.다음은 RefPtr를 사용하여 작성된 설정 함수 인스턴스입니다.
// example, not preferred style


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

RefPtr를 개별적으로 사용하면 참조 수가 점프(churn)될 수 있습니다.
// example, not preferred style; should use RefCounted and adoptRef (see below)


RefPtr createSpecialNode()
{
RefPtr a = new Node;
a->setSpecial(true);
return a;
}
RefPtr b = createSpecialNode();

토론을 고려하여 노드 대상의 인용계수 시작값이 0(잠시 후 더 많음)이라고 가정하고 a에 값을 부여하면 인용계수값이 1로 증가한다.반환 값을 만든 후 인용 계수 값이 2로 증가했고 그 다음에 a가 삭제되었고 인용 계수 값이 1로 감소했습니다.그리고 b를 만든 후 인용 계수 값이 2로 증가한 다음createSpecialNode에서 내려와서 값을 삭제한 후 인용 계수 값이 1로 줄어듭니다.
 
(컴파일러가 반환값 최적화 (return value optimization) 를 실현하면 인용 계수가 증가하고 감소하지 않습니다.)
인용계수 변환(churn)은 함수 매개 변수와 반환 값이 모두 관련된 상황에서 더욱 심각하다. 해결 방법은PassRefPtr이다.

PassRefPtr


PassRefPtr와 RefPtr는 비슷하지만 다른 점이 있습니다. PassRefPtr를 복사하거나 RefPtr 또는 다른 PassRefPtr에 PassRefPtr 값을 부여할 때 원래의 바늘 값을 0으로 설정하면 인용 계수를 바꾸지 않습니다.새로운 버전의 예를 살펴보겠습니다.
// example, not preferred style; should use RefCounted and adoptRef (see below)

PassRefPtr createSpecialNode()
{
PassRefPtr a = new Node;
a->setSpecial(true);
return a;
}
RefPtr b = createSpecialNode();

노드 대상의 초기 인용 계수 값은 0입니다. a에 값을 부여하면 인용 계수 값이 1로 증가합니다.

좋은 웹페이지 즐겨찾기