<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://ukaushik-98.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="https://ukaushik-98.github.io//" rel="alternate" type="text/html" /><updated>2025-04-22T07:01:30+00:00</updated><id>https://ukaushik-98.github.io//feed.xml</id><title type="html">ukaushik-98</title><subtitle>Personal feed that records my latests thoughts, findings, and experiences while programming.</subtitle><entry><title type="html">More Lifetimes</title><link href="https://ukaushik-98.github.io//rust/2025/01/19/more-lifetimes.html" rel="alternate" type="text/html" title="More Lifetimes" /><published>2025-01-19T17:00:00+00:00</published><updated>2025-01-19T17:00:00+00:00</updated><id>https://ukaushik-98.github.io//rust/2025/01/19/more-lifetimes</id><content type="html" xml:base="https://ukaushik-98.github.io//rust/2025/01/19/more-lifetimes.html"><![CDATA[<h3 id="owned-types">Owned Types</h3>

<h3 id="what-does-a-generic-t-actually-mean">What does a generic T actually mean?</h3>

<h3 id="the-implications-of-static">The implications of ‘static</h3>
<p>T: ‘static is some T that can be safely held indefinitely long, including up until the end of the program. T: ‘static includes all &amp;’static T however it also includes all owned types, like String, Vec, etc. The owner of some data is guaranteed that data will never get invalidated as long as the owner holds onto it, therefore the owner can safely hold onto the data indefinitely long, including up until the end of the program. T: ‘static should be read as “T can live at least as long as a ‘static lifetime” not “T has a ‘static lifetime”.</p>

<h3 id="t-a-vs-a-t">T: ‘a vs &amp;’a T</h3>

<h3 id="eliding-lifetimes">Eliding Lifetimes</h3>]]></content><author><name></name></author><category term="rust" /><summary type="html"><![CDATA[Owned Types]]></summary></entry><entry><title type="html">Send and Sync</title><link href="https://ukaushik-98.github.io//rust/2025/01/16/send-and-sync.html" rel="alternate" type="text/html" title="Send and Sync" /><published>2025-01-16T17:00:00+00:00</published><updated>2025-01-16T17:00:00+00:00</updated><id>https://ukaushik-98.github.io//rust/2025/01/16/send-and-sync</id><content type="html" xml:base="https://ukaushik-98.github.io//rust/2025/01/16/send-and-sync.html"><![CDATA[<h3 id="send">Send</h3>

<p>A type is send if and only if it’s safe to send across threads. Most types are send - the only types that break this inference are types that make assunptions on how they’re used.</p>

<h3 id="sync">Sync</h3>

<p>A type T is sync if and only if &amp;T is Send. Everything but the interior mutatbility types and RC are Sync.</p>

<h3 id="the-special-case-of-rc">The special case of RC</h3>

<p>RC is a particular type that makes strong assumptions on being single threaded. It leverages an innerstate and a counter to mantain how many references exist. Once the last reference is dropped, the entire type is dropped.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">!</span><span class="nb">Send</span> <span class="k">for</span> <span class="n">RC</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">!</span><span class="nb">Sync</span> <span class="k">for</span> <span class="n">RC</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</code></pre></div></div>

<h3 id="arc">Arc</h3>

<p>Arc is the primary way to share immutable pointers across threads, and implementation wise, it’s almost entirely the same as RC. However, since we’re in a multithreaded context, we must have the reference counter be atomic, thus the name Atomic Reference Counter.</p>

<p>Arc is interesting since we need it to be both Sync and Send. Sync is for the obvious reasons of being the primary method of sharing references across threads. Send, however, is necessary because we need drop permissions on the inner object.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">:</span> <span class="nb">Send</span> <span class="o">+</span> <span class="nb">Sync</span><span class="o">&gt;</span> <span class="nb">Send</span> <span class="k">for</span> <span class="nb">Arc</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">:</span> <span class="nb">Send</span> <span class="o">+</span> <span class="nb">Sync</span><span class="o">&gt;</span> <span class="nb">Sync</span> <span class="k">for</span> <span class="nb">Arc</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</code></pre></div></div>

<h3 id="interior-mutability-types">Interior Mutability Types</h3>

<p>These types allow mutable access to occur with only an immutable reference. Yet again, what we’re seeing here is a single threaded assumption on the usage for these types. And it makes complete sense! Afterall, we want to avoid data races entirely. In order to achieve this though, the following strict assumptions are made:</p>

<ol>
  <li>The T in the Interior Mutability type is never used outside once it’s placed in the Cell itself. Indeed, we see the enforcement of this by the Interior Mutability type taking ownership of the passed in T:</li>
</ol>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">pub</span> <span class="k">const</span> <span class="k">fn</span> <span class="nf">new</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="k">-&gt;</span> <span class="n">Cell</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</code></pre></div></div>

<ol>
  <li>Interior Mutability types are not sync. Afterall, all it takes is one immutable pointer to mutate the inner type and we can’t have that happening.</li>
</ol>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">:</span> <span class="nb">Send</span><span class="o">&gt;</span> <span class="nb">Send</span> <span class="k">for</span> <span class="n">Cell</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">!</span><span class="nb">Sync</span> <span class="k">for</span> <span class="n">Cell</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</code></pre></div></div>

<h4 id="mutex">Mutex</h4>

<p>At this point, there’s an important distinction be drawn between a Mutex and Mutex Guard. A Mutex is the type that encaplsulates thread safety primitives and provides methods on getting a lock safely. The only way to get the Guard is to call the lock function (this is an instance of a super useful pattern called typestate! It’s another topic I’ll be covering in a future post).</p>

<p>The actual thread safety trait bounds of a mutex are dictated entirely by if the inner type T is Send. The reason for the send bound is fairly obvious from the above passage but why is the Mutex not requiring T to be Sync? Afterall, it sounds counterintuitive considering that we can create any number of immutable pointers but still mutate the underlying item! This again ties back to the fact that access to the innter type first requires a lock to be taken. This means that a mutex is inherintly single threaded! Using this assumption we can safely drop the Sync requirement for a Mutex.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">:</span> <span class="nb">Send</span><span class="o">&gt;</span> <span class="nb">Send</span> <span class="k">for</span> <span class="n">Mutex</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">:</span> <span class="nb">Send</span><span class="o">&gt;</span> <span class="nb">Sync</span> <span class="k">for</span> <span class="n">Mutex</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</code></pre></div></div>

<h4 id="mutex-guard">Mutex Guard</h4>

<p>MutexGuard is not Send because it explicitly requires the thread that took the lock to drop it on certain OS. However, the guard itself can be shared via sync since an immutable pointer cannot be used to drop or mutate it’s interior structure.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">!</span><span class="nb">Send</span> <span class="k">for</span> <span class="n">MutexGuard</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="p">:</span> <span class="nb">Sync</span><span class="o">&gt;</span> <span class="nb">Sync</span> <span class="k">for</span> <span class="n">MutexGuard</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="rust" /><summary type="html"><![CDATA[Send]]></summary></entry><entry><title type="html">Exploring Lifetimes in Rust with StrSplit</title><link href="https://ukaushik-98.github.io//rust/2025/01/13/lifetimes-in-rust-playground.html" rel="alternate" type="text/html" title="Exploring Lifetimes in Rust with StrSplit" /><published>2025-01-13T06:33:44+00:00</published><updated>2025-01-13T06:33:44+00:00</updated><id>https://ukaushik-98.github.io//rust/2025/01/13/lifetimes-in-rust-playground</id><content type="html" xml:base="https://ukaushik-98.github.io//rust/2025/01/13/lifetimes-in-rust-playground.html"><![CDATA[<p>Recently, while I was working on my CityDB personal project, I ran into a few cases where I’d like to improve performance by not cloning anywhere. As such, I started diving deeper into the realm of lifetimes and variance and decided to chart out my learnings here.</p>

<p><a href="https://github.com/jonhoo">Jon Gjengset</a> did an indepth <a href="https://www.youtube.com/watch?v=rAl-9HwD858">stream</a> about lifetimes and did a deep dive on StrSplit, a C Library that takes a string and a delimeter and splits the passed in string at the first occurrence. StrSplit also mutates the input in the process, which also turns out to be especially important.</p>

<p>The port of the code that I wrote up while going through his stream can be found in my <a href="https://github.com/ukaushik-98/rust-playground/blob/master/src/strSplit/mod.rs">rust-playground repo</a>. The rest of this post will go over the issues that were discussed and how variance played a big role at guranteeing safety.</p>

<h2 id="what-is-a-lifetime">What is a lifetime?</h2>

<h3 id="defining-lifetimes">Defining Lifetimes</h3>

<h3 id="generic-lifetimes">Generic Lifetimes</h3>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">StrSplit</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="n">remainder</span><span class="p">:</span> <span class="o">&amp;</span><span class="nv">'a</span> <span class="nb">str</span><span class="p">,</span>
    <span class="n">delimeter</span><span class="p">:</span> <span class="o">&amp;</span><span class="nv">'a</span> <span class="nb">str</span>
<span class="p">}</span>

<span class="k">impl</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="n">StrSplit</span><span class="o">&lt;</span><span class="nv">'a</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="o">...</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="_-lifetime">&lt;’_&gt; Lifetime</h3>

<h2 id="variance">Variance</h2>

<p>I’ll be making a future post on variance going over yet another port of a C library but briefly variance consists of the following types:</p>

<ul>
  <li>Covariance</li>
  <li>CounterVariance</li>
  <li>Invariance</li>
</ul>

<p>The <a href="https://doc.rust-lang.org/nomicon/subtyping.html">Rustonomican</a> does a fantastic job going over the definitions and I highly recommend reviewing that.</p>

<p>A brief summary of this can be found here:
<img src="/assets/variance-table.png" alt="Variance table screenshot" /></p>

<h2 id="multiple-lifetimes">Multiple Lifetimes!</h2>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">StrSplit</span><span class="o">&lt;</span><span class="nv">'a</span><span class="p">,</span> <span class="nv">'b</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="n">remainder</span><span class="p">:</span> <span class="o">&amp;</span><span class="nv">'a</span> <span class="nb">str</span><span class="p">,</span>
    <span class="n">delimeter</span><span class="p">:</span> <span class="o">&amp;</span><span class="nv">'b</span> <span class="nb">str</span>
<span class="p">}</span>

<span class="k">impl</span><span class="o">&lt;</span><span class="nv">'a</span><span class="p">,</span> <span class="nv">'b</span><span class="o">&gt;</span> <span class="n">StrSplit</span><span class="o">&lt;</span><span class="nv">'a</span><span class="p">,</span> <span class="nv">'b</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="o">...</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="rust" /><summary type="html"><![CDATA[Recently, while I was working on my CityDB personal project, I ran into a few cases where I’d like to improve performance by not cloning anywhere. As such, I started diving deeper into the realm of lifetimes and variance and decided to chart out my learnings here.]]></summary></entry></feed>