Get the Windows bots closer to green
[WebKit-https.git] / WebKitSite / coding / RefPtr.html
1 <?php 
2     $title="RefPtr and PassRefPtr Basics";
3     include("../header.inc"); 
4 ?>
5
6 <style type="text/css">
7     .code {
8         background-color: #eee;
9         padding: 1em;
10         margin-left: 2em;
11         margin-right: 2em;
12         overflow-x: auto;
13     }
14     .comment {
15         font-style: italic;
16     }
17     p .function, p .class, p .variable, li .function, li .class, li .variable {
18         font-style: italic;
19     }
20 </style>
21
22 <h1><span class="class">RefPtr</span> and <span class="class">PassRefPtr</span> Basics</h1>
23 <div>Darin Adler</div>
24 <div>first draft, 2007-03-24</div>
25
26 <h2>History</h2>
27
28 <p>Many objects in WebKit are reference counted. The pattern used is that classes have
29 member functions <span class="function">ref</span> and <span class="function">deref</span>
30 that increment and decrement the reference count. Each call to <span class="function">ref</span>
31 has to be matched by a call to <span class="function">deref</span>. When the reference count hits 0,
32 the object is deleted. Many of these classes create new objects with a reference count of 0; this
33 is referred to as the floating state. An object in floating state must have <span class="function">ref</span> and then
34 <span class="function">deref</span> called on it before it will be deleted. Many classes in WebCore implement this by
35 inheriting from the <span class="class">Shared</span> class template.</p>
36
37 <p>Back in 2005, we discovered that there were many memory leaks, especially in WebCore
38 editor code, caused either by mismatches of <span class="function">ref</span> and
39 <span class="function">deref</span> calls or by objects that were created with
40 <span class="function">new</span> that never got a <span class="function">ref</span>
41 call at all and remained in the floating state.</p>
42
43 <p>We decided that we’d like
44 to use smart pointers to mitigate the problem. However, some early experiments showed that
45 smart pointers led to additional manipulation of reference counts that hurt performance.
46 For example, if a function took a smart pointer as a parameter and returned that same smart
47 pointer as a return value, just passing the parameter and returning the value would increment
48 and then decrement the reference count two to four times
49 as the object moved from one smart pointer to another. So we looked for an
50 idiom that would let us use smart pointers and avoid this reference count churn.</p>
51
52 <p>The inspiration for a solution came from the C++ standard class template <span class="class">auto_ptr</span>.
53 These objects implement a model where assignment is transfer of ownership. When you assign
54 from one <span class="class">auto_ptr</span> to another, the donor becomes 0.</p>
55
56 <p>Maciej Stachowiak devised a pair of class templates, <span class="class">RefPtr</span>
57 and <span class="class">PassRefPtr</span>, that implement this scheme
58 for WebCore’s intrusive reference counting.</p>
59
60 <h2>Raw pointers</h2>
61
62 <p>When discussing smart pointers such as the <span class="class">RefPtr</span>
63 class template we use the term raw pointer to refer to the C++ language’s built in pointer type.
64 Here’s the canonical setter function, written with raw pointers:</p>
65
66 <pre class="code"><span class="comment">// example, not preferred style</span>
67
68 class Document {
69     <span class="comment">[...]</span>
70     Title* m_title;
71 }
72
73 Document::Document()
74     : m_title(0)
75 {
76 }
77
78 Document::~Document()
79 {
80     if (m_title)
81         m_title-&gt;deref();
82 }
83
84 void Document::setTitle(Title* t)
85 {
86     if (t)
87         t-&gt;ref();
88     if (m_title)
89         m_title-&gt;deref();
90     m_title = t;
91 }</pre>
92
93 <h2><span class="class">RefPtr</span></h2>
94
95 <p><span class="class">RefPtr</span> is a simple smart pointer class that calls <span class="function">ref</span>
96 on incoming values and
97 <span class="function">deref</span> on outgoing values.
98 <span class="class">RefPtr</span> works on any object with both a <span class="function">ref</span> and
99 a <span class="function">deref</span> member function.
100 Here’s the setter function example, written with <span class="class">RefPtr</span>:</p>
101
102 <pre class="code"><span class="comment">// example, not preferred style</span>
103  
104 class Document {
105     <span class="comment">[...]</span>
106     RefPtr&lt;Title&gt; m_title;
107 }
108
109 void Document::setTitle(Title* t)
110 {
111     m_title = t;
112 }</pre>
113
114 <p>Use of <span class="class">RefPtr</span> alone can lead to reference count churn.</p>
115
116 <pre class="code"><span class="comment">// example, not preferred style</span>
117  
118 RefPtr&lt;Node&gt; createSpecialNode()
119 {
120     RefPtr&lt;Node&gt; a = new Node;
121     a-&gt;setSpecial(true);
122     return a;
123 }
124
125 RefPtr&lt;Node&gt; b = createSpecialNode();</pre>
126
127 <p>The node object starts with a reference count of 0. When it’s assigned to <span class="variable">a</span>,
128 the reference count is incremented to 1. The reference count is incremented to 2 to
129 create the return value, then decremented back to 1 when <span class="variable">a</span> is destroyed.
130 Then the reference count is incremented to 2 to create <span class="variable">b</span>, and then decremented back
131 to 1 when the return value of <span class="function">createSpecialNode</span> is destroyed.</p>
132
133 <p>(This analysis ignores the possibility that the compiler might implement the
134 <a href="http://www.awprofessional.com/articles/article.asp?p=25033&amp;seqNum=3&amp;rl=1">return value optimization</a>.
135 If the compiler does, some of the reference count churn may be mitigated.)</p>
136
137 <p>The overhead of reference count churn is even greater when both function arguments and return
138 values are involved. The solution is <span class="class">PassRefPtr</span>.</p>
139
140 <h2><span class="class">PassRefPtr</span></h2>
141
142 <p><span class="class">PassRefPtr</span> is like <span class="class">RefPtr</span> with a difference.
143 When you copy a <span class="class">PassRefPtr</span> or
144 assign the value of a <span class="class">PassRefPtr</span> to a <span class="class">RefPtr</span> or
145 another <span class="class">PassRefPtr</span>, the original
146 pointer value is set to 0; the operation is done without any change to the reference count.
147 Let’s take a look at a new version of our example:</p>
148
149 <pre class="code"><span class="comment">// example, not preferred style</span>
150
151 PassRefPtr&lt;Node&gt; createSpecialNode()
152 {
153     PassRefPtr&lt;Node&gt; a = new Node;
154     a-&gt;setSpecial(true);
155     return a;
156 }
157
158 RefPtr&lt;Node&gt; b = createSpecialNode();</pre>
159
160 <p>The node object starts with a reference count of 0. When it’s assigned to <span class="variable">a</span>,
161 the reference count is incremented to 1. Then <span class="variable">a</span> gets set to 0 when the return
162 value <span class="class">PassRefPtr</span> is created. Then the return value is set to 0 when
163 <span class="variable">b</span> is created.</p>
164
165 <p>However, as the Safari team learned when we started programming with <span class="class">PassRefPtr</span>,
166 the rule that a pointer becomes 0 when it’s assigned to another variable can easily lead to mistakes.</p>
167
168 <pre class="code"><span class="comment">// example, not preferred style</span>
169  
170 static RefPtr&lt;Ring&gt; g_oneRingToRuleThemAll;
171
172 void finish(PassRefPtr&lt;Ring&gt; ring)
173 {
174     g_oneRingToRuleThemAll = ring;
175     <span class="comment">...</span>
176     ring-&gt;wear();
177 }</pre>
178
179 <p>By the time <span class="function">wear</span> is called, <span class="variable">ring</span>
180 is already 0. To avoid this, we recommend <span class="class">PassRefPtr</span> only for
181 function argument and result types, copying arguments into <span class="class">RefPtr</span>
182 local variables.</p>
183
184 <pre class="code">static RefPtr&lt;Ring&gt; g_oneRingToRuleThemAll;
185
186 void finish(PassRefPtr&lt;Ring&gt; prpRing)
187 {
188     RefPtr&lt;Ring&gt; ring = prpRing;
189     g_oneRingToRuleThemAll = ring;
190     <span class="comment">...</span>
191     ring-&gt;wear();
192 }</pre>
193
194 <h2>Mixing <span class="class">RefPtr</span> and <span class="class">PassRefPtr</span></h2>
195
196 <p>Since we recommend use of <span class="class">RefPtr</span> in all cases except when passing arguments to or
197 returning values from a function, there will be times when you have a <span class="class">RefPtr</span>
198 and wish to transfer ownership as <span class="class">PassRefPtr</span> does.
199 <span class="class">RefPtr</span> has a member function named
200 <span class="function">release</span> which does the trick. It sets the value of the original
201 <span class="class">RefPtr</span> to 0 and constructs a <span class="class">PassRefPtr</span>, without
202 changing reference counts.</p>
203
204 <pre class="code">PassRefPtr&lt;Node&gt; createSpecialNode()
205 {
206     RefPtr&lt;Node&gt; a = new Node;
207     a-&gt;setCreated(true);
208     return a.release();
209 }
210
211 RefPtr&lt;Node&gt; b = createSpecialNode();</pre>
212
213 <p>This keeps the efficiency of <span class="class">PassRefPtr</span> while reducing the chance
214 that its relatively tricky semantics will cause problems.</p>
215
216 <h2>Mixing with raw pointers</h2>
217
218 <p>When using a <span class="class">RefPtr</span> to call a function that takes a raw pointer,
219 use <span class="function">get</span>.</p>
220
221 <pre class="code">printNode(stderr, a.get());</pre>
222
223 <p>However, there are operations that can be done on a <span class="class">RefPtr</span>
224 or <span class="class">PassRefPtr</span> directly, without resorting to an explicit <span class="function">get</span> call.</p>
225
226 <pre class="code">RefPtr&lt;Node&gt; a = createSpecialNode();
227 Node* b = getOrdinaryNode();
228
229 <span class="comment">// the * operator</span>
230 *a = value;
231
232 <span class="comment">// the -&gt; operator</span>
233 a-&gt;clear();
234
235 <span class="comment">// null check in an if statement</span>
236 if (a)
237     log("not empty");
238
239 <span class="comment">// the ! operator</span>
240 if (!a)
241     log("empty");
242
243 <span class="comment">// the == and != operators, mixing with raw pointers</span>
244 if (a == b)
245     log("equal");
246 if (a != b)
247     log("not equal");
248
249 <span class="comment">// some type casts</span>
250 RefPtr&lt;DerivedNode&gt; d = static_pointer_cast&lt;DerivedNode&gt;(a);</pre>
251
252 <p>Normally, <span class="class">RefPtr</span> and <span class="class">PassRefPtr</span>
253 enforce a simple rule; they always balance <span class="function">ref</span> and
254 <span class="function">deref</span> calls, guaranteeing a programmer can’t miss a
255 <span class="function">deref</span>. But in the case where we have a raw pointer,
256 already have a reference count, and want to transfer ownership the
257 <span class="function">adoptRef</span> function should be used.</p>
258
259 <pre class="code"><span class="comment">// warning, requires a pointer that already has a ref</span>
260 RefPtr&lt;Node&gt; node = adoptRef(rawNodePointer);</pre>
261
262 <p>To transfer from a <span class="class">RefPtr</span> to a raw pointer without
263 changing the reference count, <span class="class">PassRefPtr</span> provides the
264 <span class="function">releaseRef</span> function.</p>
265
266 <pre class="code"><span class="comment">// warning, results in a pointer that must get an explicit deref</span>
267 RefPtr&lt;Node&gt; node = createSpecialNode();
268 Node* rawNodePointer = node.release().releaseRef();</pre>
269
270 <p>Since <span class="function">releaseRef</span> is rarely used, it’s provided only in the
271 <span class="class">PassRefPtr</span> class, hence the need to call <span class="function">release</span>,
272 then <span class="function">releaseRef</span>. If we find this is used often we could
273 provide <span class="function">releaseRef</span> for <span class="class">RefPtr</span> too.</p>
274
275 <h2>Guidelines</h2>
276
277 <p>We’ve developed these guidelines for use of <span class="class">RefPtr</span>
278 and <span class="class">PassRefPtr</span> in WebKit code.</p>
279
280 <h3>Local variables</h3>
281 <ul>
282 <li>If ownership and lifetime are guaranteed, a local variable can be a raw pointer.</li>
283 <li>If the code needs to hold ownership or guarantee lifetime, a local variable should
284 be a <span class="class">RefPtr</span>.</li>
285 <li>Local variables should never be <span class="class">PassRefPtr</span>.</li>
286 </ul>
287
288 <h3>Data members</h3>
289 <ul>
290 <li>If ownership and lifetime are guaranteed, a data member can be a raw pointer.</li>
291 <li>If the class needs to hold ownership or guarantee lifetime, the data member should
292 be a <span class="class">RefPtr</span>.</li>
293 <li>Data members should never be <span class="class">PassRefPtr</span>.</li>
294 </ul>
295
296 <h3>Function arguments</h3>
297 <ul>
298 <li>If a function does not take ownership of an object, the argument should be a raw pointer.</li>
299 <li>If a function does take ownership of an object, the argument should be a <span class="class">PassRefPtr</span>.
300 This includes most setter functions.
301 Unless the use of the argument is very simple, the argument should be transferred to a
302 <span class="class">RefPtr</span> at the start of the function; the argument can be named with
303 a “prp” prefix in such cases.</li>
304 </ul>
305
306 <h3>Function results</h3>
307 <ul>
308 <li>If a function’s result is an object, but ownership is not being transferred, the result
309 should be a raw pointer. This includes most getter functions.</li>
310 <li>If a function’s result is a new object or ownership is being transferred for any other
311 reason, the result should be a <span class="class">PassRefPtr</span>.
312 Since local variables are typically <span class="class">RefPtr</span>, it’s common to call
313 <span class="function">release</span> in the return statement to transfer the
314 <span class="class">RefPtr</span> to the <span class="class">PassRefPtr</span>.</li>
315 </ul>
316
317 <h3>New objects</h3>
318 <ul>
319 <li>New objects should be put into a <span class="class">RefPtr</span> as soon as possible
320 after creation to avoid possibly leaking an object while it’s in a floating state.</li>
321 <li>Best idiom is to use a private constructor and have a public factory function that
322 returns a <span class="class">PassRefPtr</span>.</li>
323 </ul>
324
325 <h2>Improving this document</h2>
326
327 <p>What frequently asked questions are not covered by this document?</p>
328
329 <p>Which of these topics should also be covered by this document?</p>
330
331 <ul>
332
333 <li>The “protector” idiom, where a local RefPtr variable is used to keep an object alive.</li>
334
335 <li>Perils of programming with floating objects.</li>
336
337 <li>Why we should use create functions that return <span class="class">PassRefPtr</span>
338 rather than use <span class="function">new</span> directly.</li>
339
340 <li>Perils of programming with <span class="class">TreeShared</span>.</li>
341
342 <li>Our desire to rename <span class="class">Shared</span> to <span class="class">RefCounted</span>.</li>
343
344 <li>Our desire to eliminate <span class="class">TreeShared</span> and instead have
345 <span class="variable">m_firstChild</span> and <span class="variable">m_next</span> be
346 <span class="class">ListRefPtr</span> or the equivalent.</li>
347
348 <li>How we we mix reference counting with garbage collection to implement the DOM
349 and the JavaScript and Objective-C DOM bindings.</li>
350
351 <li>Comparison of our intrusive reference counting with other schemes such as the
352 external reference counting in Boost <span class="class">shared_ptr</class>.</li>
353
354 <li>The <span class="class">OwnPtr</span> class template, and how
355 <span class="class">auto_ptr</span> functions as a <span class="class">PassOwnPtr</span>.</li>
356
357 <li>The <span class="class">OwnArrayPtr</span> class template,
358 and the lack of a <span class="class">PassOwnArrayPtr</span>.</li>
359
360 <li>The <span class="class">RetainPtr</span> class template,
361 and the lack of a <span class="class">PassRetainPtr</span>.</li>
362
363 <li>The <span class="class">DocPtr</span> class template.</li>
364
365 <li>The <span class="class">ListRefPtr</span> class template.</li>
366
367 </ul>
368
369 <p>Any other ideas about improving the clarity, scope, or presentation?</p>
370
371 <?php
372     include("../footer.inc");
373 ?>