<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>~iany/ Memory Management</title><link>https://blog.iany.me/tags/memory-management/</link><description>Recent content in Memory Management «~iany/»</description><language>en-US</language><managingEditor>me@iany.me (Ian Yang)</managingEditor><webMaster>me@iany.me (Ian Yang)</webMaster><copyright>CC-BY-SA 4.0</copyright><lastBuildDate>Sun, 24 Feb 2019 07:35:47 +0000</lastBuildDate><atom:link href="https://blog.iany.me/tags/memory-management/index.xml" rel="self" type="application/rss+xml"/><item><title>Rust Cell and RefCell</title><link>https://blog.iany.me/2019/02/rust-cell-and-refcell/</link><pubDate>Sun, 24 Feb 2019 07:35:47 +0000</pubDate><author>me@iany.me (Ian Yang)</author><guid>https://blog.iany.me/2019/02/rust-cell-and-refcell/</guid><description>&lt;p&gt;In Rust document, &lt;em&gt;Cell&lt;/em&gt; is “A mutable memory location”, and &lt;em&gt;RefCell&lt;/em&gt; is “A mutable memory location with dynamically checked borrow rules”.&lt;/p&gt;
&lt;p&gt;They both provide “interior mutability”, where you can modify the value stored in cell via immutable reference of the cell.&lt;/p&gt;
&lt;p&gt;They both have an API &lt;code&gt;get_mut&lt;/code&gt; to return a mutable reference to the underlying data. This method requires a mutable reference to the cell, which guarantees that the callee has exclusive ownership of the cell.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-rust"&gt;pub fn get_mut(&amp;amp;mut self) -&amp;gt; &amp;amp;mut T
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The difference is how they implement interior mutability. &lt;em&gt;Cell&lt;/em&gt; copies or moves contained value, while &lt;em&gt;RefCell&lt;/em&gt; allows both mutable and immutable reference borrowing. I will try to explain the difference via their APIs in this article.&lt;/p&gt;
&lt;h2 id="cell"&gt;Cell&lt;/h2&gt;
&lt;p&gt;In the old version of Rust, &lt;em&gt;Cell&lt;/em&gt; requires the wrapped type to be &lt;em&gt;Copy&lt;/em&gt;. Many articles still contain such outdated and misleading information. Indeed &lt;em&gt;Cell&lt;/em&gt; has two different sets of APIs in a newer version.&lt;/p&gt;
&lt;p&gt;The first set is the Copy API. It requires a &lt;em&gt;Copy&lt;/em&gt; wrapper, and contains methods &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt;. The method &lt;code&gt;get&lt;/code&gt; returns a copy of the contained value, and &lt;code&gt;set&lt;/code&gt; stores a copy of the argument &lt;code&gt;val&lt;/code&gt; as the new value.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-rust"&gt;// impl&amp;lt;T: Copy&amp;gt; Cell&amp;lt;T&amp;gt;
pub fn get(&amp;amp;self) -&amp;gt; T
// impl&amp;lt;T&amp;gt; Cell&amp;lt;T&amp;gt;
pub fn set(&amp;amp;self, val: T)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another set is the Move API. It has two methods &lt;code&gt;take&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt;. The method &lt;code&gt;take&lt;/code&gt; moves out the contained value, leaving &lt;code&gt;Default::default()&lt;/code&gt; in its place. The call &lt;code&gt;set&lt;/code&gt; also works for non-copyable type, where it moves the argument into the cell.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-rust"&gt;// impl&amp;lt;T: Default&amp;gt; Cell&amp;lt;T&amp;gt;
pub fn take(&amp;amp;self) -&amp;gt; T
// impl&amp;lt;T&amp;gt; Cell&amp;lt;T&amp;gt;
pub fn set(&amp;amp;self, val: T)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The method &lt;code&gt;replace&lt;/code&gt; is an alternative of &lt;code&gt;take&lt;/code&gt;, when &lt;code&gt;T&lt;/code&gt; does not implement &lt;em&gt;Default&lt;/em&gt; or the new value is known in advance when taking the value.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-rust"&gt;// impl&amp;lt;T&amp;gt; Cell&amp;lt;T&amp;gt;
pub fn replace(&amp;amp;self, val: T) -&amp;gt; T
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An important property of &lt;em&gt;Cell&lt;/em&gt; is that the cell cannot tell you what&amp;rsquo;s contained in the cell via a reference. You either copy the contained value, or modify the cell and move out the value.&lt;/p&gt;
&lt;h2 id="refcell"&gt;RefCell&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;RefCell&lt;/em&gt; allows borrowing immutable or mutable reference to the contained value. It tracks the borrows at runtime, via &lt;code&gt;borrow&lt;/code&gt; and &lt;code&gt;borrow_mut&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pub fn borrow(&amp;amp;self) -&amp;gt; Ref&amp;lt;T&amp;gt;
pub fn borrow_mut(&amp;amp;self) -&amp;gt; RefMut&amp;lt;T&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The method &lt;code&gt;borrow&lt;/code&gt; grants temporary access to the contained value via immutable reference. Multiple immutable borrows can be taken out at the same time. It panics if the value is currently mutably borrowed.&lt;/p&gt;
&lt;p&gt;The API &lt;code&gt;borrow_mut&lt;/code&gt; mutably borrows the wrapped value. It panics if the value is currently borrowed, either mutably or immutably.&lt;/p&gt;
&lt;p&gt;The runtime tracking certainly has overheads, and &lt;code&gt;RefCell&lt;/code&gt; also can lead to runtime panics.&lt;/p&gt;</description><category domain="https://blog.iany.me/post/">Posts</category><category domain="https://blog.iany.me/tags/memory-management/">Memory Management</category><category domain="https://blog.iany.me/tags/rust/">Rust</category></item></channel></rss>