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