RefPtr.html 17 KB

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