<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anton Dolganin</title>
    <description>The latest articles on Forem by Anton Dolganin (@antonds).</description>
    <link>https://forem.com/antonds</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3239903%2F685d8291-a6b2-45fa-8b3b-64f99c6e3219.jpg</url>
      <title>Forem: Anton Dolganin</title>
      <link>https://forem.com/antonds</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/antonds"/>
    <language>en</language>
    <item>
      <title>Did you know that a shell is just an ordinary program?</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Sat, 16 May 2026 14:11:20 +0000</pubDate>
      <link>https://forem.com/antonds/did-you-know-that-a-shell-is-just-an-ordinary-program-2f0b</link>
      <guid>https://forem.com/antonds/did-you-know-that-a-shell-is-just-an-ordinary-program-2f0b</guid>
      <description>&lt;p&gt;Many people think that the command line (bash, zsh) where we type our commands is some deeply integrated, magical part of the operating system.&lt;/p&gt;

&lt;p&gt;In reality, a shell is just the starting program on your server. When you log in via SSH, the system looks into the user's configuration file and runs whatever is specified there. If you replace &lt;code&gt;/bin/bash&lt;/code&gt; with the path to Python, you'll end up in the Python interpreter. If you specify &lt;code&gt;/usr/bin/top&lt;/code&gt;, the task manager will open, and exiting it will immediately close your SSH session.&lt;/p&gt;

&lt;p&gt;But how does a shell work under the hood? Fundamentally, it's just an infinite loop. Here is what its minimalist skeleton looks like in modern C.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimal Shell (based on the UNIX pattern)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;sys/wait.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define MAXLINE 4096
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MAXLINE&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%% "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAXLINE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;pid_t&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fork&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fork error"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* child process */&lt;/span&gt;
            &lt;span class="n"&gt;execlp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="cm"&gt;/* if execlp returns control, then an error occurred. */&lt;/span&gt;
            &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"couldn't execute: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;127&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="cm"&gt;/* parent process */&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;waitpid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;perror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"waitpid error"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_FAILURE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%% "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EXIT_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works under the hood&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The entire essence of a classic UNIX shell boils down to the fork-exec-wait pattern, which can be described in five simple steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read a line of input from the user in a loop.&lt;/li&gt;
&lt;li&gt;Strip the newline character left after pressing Enter.&lt;/li&gt;
&lt;li&gt;Fork the process — ask the OS kernel to create an exact copy of our program.&lt;/li&gt;
&lt;li&gt;If it's the child process, replace ourselves with the program whose path the user entered.&lt;/li&gt;
&lt;li&gt;If it's the parent (our original shell), simply wait for the child to finish, and then print the &lt;code&gt;%&lt;/code&gt; prompt again.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What is the "magic of fork"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After calling the &lt;code&gt;fork()&lt;/code&gt; function, the operating system clones the process. Both processes continue execution from the exact same line of code (the return from the &lt;code&gt;fork&lt;/code&gt; function). They differ in only one way: in the child process, the function returns &lt;code&gt;0&lt;/code&gt;, while the parent receives the ID of the newly created clone. This value acts as a fork in the road, forcing the processes down different branches of the &lt;code&gt;if-else&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important caveat:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This code is intentionally bare-bones and serves purely educational purposes. It doesn't know how to handle parameters (a command like &lt;code&gt;ls -l&lt;/code&gt; will throw an error because the system will look for a single executable file with a space in its name), and it doesn't support built-in commands like &lt;code&gt;cd&lt;/code&gt; or &lt;code&gt;exit&lt;/code&gt;, nor pipes. A real shell does a massive amount of work tokenizing your input string and configuring file descriptors before calling exec. Nevertheless, absolutely every terminal is built on top of this elegant mechanism.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>programming</category>
      <category>c</category>
    </item>
    <item>
      <title>How the CPU Breaks Your Multithreading (False Sharing)</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Fri, 08 May 2026 10:23:59 +0000</pubDate>
      <link>https://forem.com/antonds/how-the-cpu-breaks-your-multithreading-false-sharing-4cm9</link>
      <guid>https://forem.com/antonds/how-the-cpu-breaks-your-multithreading-false-sharing-4cm9</guid>
      <description>&lt;p&gt;Imagine a typical scenario: you're optimizing a high-load backend or a network service. It doesn't matter what language you use — C, C++, Java, Go, or C#. You have several threads, and you decide to get rid of slow locks. After all, mutexes are a bottleneck, right?&lt;/p&gt;

&lt;p&gt;You apply a classic pattern: instead of threads elbowing each other around a shared variable, you give each thread (or goroutine) its own independent counter. No shared data — no conflicts. You run your load tests expecting beautiful linear scaling, but the profiler shows something weird. The threads seem to still be waiting in line, and the code runs almost slower on a multi-core machine than on a single core.&lt;/p&gt;

&lt;p&gt;How is this possible if there are no more locks in the code?&lt;/p&gt;

&lt;p&gt;Welcome to the real world, where your programming language's abstractions crash into harsh hardware realities. The problem is that the CPU doesn't care how you logically separated variables in your code. The culprit is &lt;strong&gt;False Sharing&lt;/strong&gt; — an invisible hardware lock.&lt;/p&gt;

&lt;p&gt;To understand why your perfect lock-free code is lagging, we need to look under the hood and see how the CPU actually reads memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache Lines: How the CPU Sees Memory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The CPU &lt;strong&gt;never reads memory one byte at a time&lt;/strong&gt;. It's simply too slow. Instead, it loads data in blocks called &lt;strong&gt;cache lines&lt;/strong&gt;. In modern architectures, a single cache line is usually &lt;strong&gt;64 bytes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the CPU needs a 4-byte variable, it grabs it along with the neighboring 60 bytes and puts the whole block into its cache.&lt;/p&gt;

&lt;p&gt;Here is a very simplified memory hierarchy by access time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L1 Cache (per core)&lt;/strong&gt;: the fastest (~1 nanosecond), but small.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L2 Cache (per core)&lt;/strong&gt;: slightly slower (~4 nanoseconds), but larger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L3 Cache (shared across all cores)&lt;/strong&gt;: slow (~15-20 nanoseconds), but massive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RAM&lt;/strong&gt;: the "turtle" (~100 nanoseconds).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Illusion of Independence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's go back to our network packets. We created a C structure holding counters for two cores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PacketCounters&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;core1_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 4 bytes&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;core2_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 4 bytes&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PacketCounters&lt;/span&gt; &lt;span class="n"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; Isn't the structure a single entity? How can one core update part of it while another updates the rest?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer lies in the fact that the CPU doesn't care about structures. Structures only exist in the programming language. To the processor, it's just a &lt;strong&gt;continuous block of memory&lt;/strong&gt;. &lt;code&gt;core1_count&lt;/code&gt; and &lt;code&gt;core2_count&lt;/code&gt; sit right next to each other in memory. Together they take up only 8 bytes, which means &lt;strong&gt;they are guaranteed to end up in the exact same 64-byte cache line&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Ping-Pong Effect, or the "Hardware Mutex"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We thought we got rid of the mutex because &lt;code&gt;Core 1&lt;/code&gt; only writes to &lt;code&gt;core1_count&lt;/code&gt;, and &lt;code&gt;Core 2&lt;/code&gt; only writes to &lt;code&gt;core2_count&lt;/code&gt;. But here is what happens at the hardware level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Core 1&lt;/strong&gt; increments core1_count. It loads the entire 64-byte line into its L1 cache and changes the value there.&lt;/li&gt;
&lt;li&gt;The CPU's cache coherence protocol sees that the data in the line has changed. To prevent desynchronization, it &lt;strong&gt;invalidates (marks as garbage)&lt;/strong&gt; this exact cache line in the caches of all other cores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core 2&lt;/strong&gt; wants to increment core2_count. It tries to access its L1 cache, but sees that its cache line has been dropped! It is forced to re-fetch it from the slow L3 cache or RAM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core 2&lt;/strong&gt; changes the value and... invalidates the cache for &lt;strong&gt;Core 1&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even if the cores are working strictly in parallel, this 64-byte memory line bounces between them like a ping-pong ball. An "invisible mutex" is formed at the hardware level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Fix It?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the problem is that independent data is sitting too close, the solution is obvious — &lt;strong&gt;move them apart&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We need to make sure that each core's counter lives in its own cache line. To do this, we pad the variables (adding empty bytes) to blow up the size to 64 bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdalign.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Using compiler alignment&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PaddedCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;alignas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="c1"&gt;// The compiler will automatically add 60 bytes of padding here&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;PaddedCounter&lt;/span&gt; &lt;span class="n"&gt;counters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Now they are definitely in different cache lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we artificially stretched the size of &lt;code&gt;PaddedCounter&lt;/code&gt; to 64 bytes, &lt;code&gt;counters[0]&lt;/code&gt; (for Core 1) and &lt;code&gt;counters[1]&lt;/code&gt; (for Core 2) will now be placed in completely separate memory blocks. They are guaranteed to sit in different cache lines and will no longer reset each other's caches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Lock-free programming is great. But if you forget that the CPU manages memory in 64-byte chunks, you might end up with code that runs slower on a multi-core machine than on a single thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 A quick footnote: is a cache line always 64 bytes?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the examples above, we hardcoded 64 bytes — this is the standard for the vast majority of modern processors. But in production code, manually writing magic numbers is a bad practice (what if the code runs on an architecture with a 128-byte cache?). Therefore, in real projects, the size is determined dynamically: for example, C++17 added the cross-platform constant &lt;code&gt;std::hardware_destructive_interference_size&lt;/code&gt;, and in Java, developers don't have to think about bytes at all — just adding the &lt;code&gt;@Contended&lt;/code&gt; annotation tells the JVM to automatically spread the data across different cache lines.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>multithreading</category>
      <category>cpu</category>
    </item>
    <item>
      <title>Rust: Transparent Wrappers with Deref Coercion</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Thu, 08 Jan 2026 16:41:00 +0000</pubDate>
      <link>https://forem.com/antonds/rust-transparent-wrappers-with-deref-coercion-4bgi</link>
      <guid>https://forem.com/antonds/rust-transparent-wrappers-with-deref-coercion-4bgi</guid>
      <description>&lt;p&gt;The &lt;strong&gt;Newtype&lt;/strong&gt; pattern (&lt;code&gt;struct Username(String)&lt;/code&gt;) is great for type safety, but it often feels clunky because you lose direct access to the inner type's methods. Implementing the &lt;code&gt;Deref&lt;/code&gt; trait solves this, making your wrapper behave like the data it holds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use It&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Cost Abstraction:&lt;/strong&gt; Strict type differentiation (e.g., &lt;code&gt;Username&lt;/code&gt; vs. &lt;code&gt;Password&lt;/code&gt;) without the boilerplate of proxying every method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Ergonomics:&lt;/strong&gt; Seamlessly use methods like &lt;code&gt;.len()&lt;/code&gt;, &lt;code&gt;.is_empty()&lt;/code&gt;, or &lt;code&gt;.contains()&lt;/code&gt; directly on your custom struct.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Implementation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Deref&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nf"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Deref&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// The type we want to "mimic"&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;deref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="na"&gt;.0&lt;/span&gt; &lt;span class="c1"&gt;// Return a reference to the inner value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In Action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thanks to Deref Coercion, the compiler automatically triggers &lt;code&gt;.deref()&lt;/code&gt; when it encounters a type mismatch that can be resolved by a reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Username&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Anton"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Direct access to &amp;amp;str methods&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;        
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 

&lt;span class="c1"&gt;// 2. Passing to functions expecting &amp;amp;str&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, {s}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Coercion kicks in here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Intent Matters:&lt;/strong&gt; Only use this when the wrapper is conceptually a “smart pointer” or a transparent extension. If the inner type’s methods could break your struct’s internal logic, stick to manual method delegation.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>deref</category>
      <category>newtype</category>
    </item>
    <item>
      <title>Rust CI: Security, Dependency Policy, Coverage Gate, and Fast Builds</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Sun, 23 Nov 2025 16:52:38 +0000</pubDate>
      <link>https://forem.com/antonds/rust-ci-security-dependency-policy-coverage-gate-and-fast-builds-5f5b</link>
      <guid>https://forem.com/antonds/rust-ci-security-dependency-policy-coverage-gate-and-fast-builds-5f5b</guid>
      <description>&lt;p&gt;A typical GitHub Actions workflow for Rust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install cargo-audit, cargo-deny, tarpaulin, chef&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cargo install cargo-audit cargo-deny cargo-tarpaulin cargo-chef&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Security check&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cargo audit&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dependency policy check&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cargo deny check&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test coverage gate&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cargo tarpaulin --fail-under &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build using cargo chef&lt;/span&gt;
    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;cargo chef prepare --recipe-path recipe.json&lt;/span&gt;
      &lt;span class="s"&gt;cargo chef cook --recipe-path recipe.json&lt;/span&gt;
      &lt;span class="s"&gt;cargo build --release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;performs security validation,&lt;/li&gt;
&lt;li&gt;enforces dependency and license policies,&lt;/li&gt;
&lt;li&gt;ensures test coverage quality,&lt;/li&gt;
&lt;li&gt;and builds your Rust project quickly using dependency caching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What each step does:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security check (cargo-audit)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cargo audit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scans Cargo.lock for vulnerable, deprecated, or compromised dependencies using the RustSec advisory database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependency policy check (cargo-deny)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cargo deny check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validates your dependency graph: licenses, banned crates, duplicates, and other policy rules.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test coverage gate (cargo-tarpaulin)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cargo tarpaulin --fail-under &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Measures test coverage and fails the CI pipeline if coverage is below 80%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fast build using cargo-chef&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="s"&gt;cargo chef prepare --recipe-path recipe.json&lt;/span&gt;
&lt;span class="s"&gt;cargo chef cook --recipe-path recipe.json&lt;/span&gt;
&lt;span class="s"&gt;cargo build --release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;prepare: generates a dependency recipe.&lt;/li&gt;
&lt;li&gt;cook: builds and caches dependencies separately.&lt;/li&gt;
&lt;li&gt;cargo build --release: final build using a warmed dependency cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;via &lt;a href="https://www.youtube.com/@letsgetrusty" rel="noopener noreferrer"&gt;@Let's Get Rusty&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>devops</category>
      <category>githubactions</category>
      <category>security</category>
    </item>
    <item>
      <title>Makefiles — add a make help command</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Wed, 19 Nov 2025 17:48:57 +0000</pubDate>
      <link>https://forem.com/antonds/makefiles-add-a-make-help-command-1o7l</link>
      <guid>https://forem.com/antonds/makefiles-add-a-make-help-command-1o7l</guid>
      <description>&lt;p&gt;If you’re using Makefiles — add a make help command.&lt;br&gt;
It auto-parses comments and shows all tasks instantly.&lt;/p&gt;

&lt;p&gt;Simple hack, huge productivity boost.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;help&lt;/span&gt;:
    @awk &lt;span class="s1"&gt;'BEGIN {FS=":"} \
    /^#/ {comment=substr($$0,3)} \
    /^[a-zA-Z0-9_-]+:/ {printf "\033[36m%-20s\033[0m %s\n", $$1, comment}'&lt;/span&gt; Makefile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow4jw0iiqbhfemjsmnl0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow4jw0iiqbhfemjsmnl0.jpg" alt=" " width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>makefile</category>
      <category>devtips</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Scraping and Summarizing LinkedIn Jobs with a Chrome Extension + ChatGPT</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Tue, 09 Sep 2025 13:06:40 +0000</pubDate>
      <link>https://forem.com/antonds/scraping-and-summarizing-linkedin-jobs-with-a-chrome-extension-chatgpt-33m0</link>
      <guid>https://forem.com/antonds/scraping-and-summarizing-linkedin-jobs-with-a-chrome-extension-chatgpt-33m0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xoh6x5eytw5o5995wxo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xoh6x5eytw5o5995wxo.png" alt=" " width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intro&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scrolling through endless job descriptions on LinkedIn can be overwhelming.&lt;/p&gt;

&lt;p&gt;I wanted a faster way to get the essence of a role — so I built a &lt;a href="https://github.com/anton-ds/linkedin-scraper-ext" rel="noopener noreferrer"&gt;small Chrome extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This extension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scrapes job descriptions from LinkedIn (directly from the job page)&lt;/li&gt;
&lt;li&gt;Cleans up the text (removes tags, weird spacing, extra line breaks)&lt;/li&gt;
&lt;li&gt;Sends it to ChatGPT with a custom prompt&lt;/li&gt;
&lt;li&gt;Displays a structured summary right inside the popup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All processing happens locally in the browser, and ChatGPT is called directly via API. No backend, no middlemen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Works&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the extension locally (Load unpacked in chrome://extensions)&lt;/li&gt;
&lt;li&gt;Open any LinkedIn job post&lt;/li&gt;
&lt;li&gt;Click the extension icon → job description appears in a popup&lt;/li&gt;
&lt;li&gt;Hit Send to ChatGPT → receive a clean, structured summary (role, requirements, stack, seniority)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why Build It?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I often check LinkedIn job posts but most descriptions are long walls of text.&lt;/p&gt;

&lt;p&gt;This extension reduces noise and lets me quickly see if a role is relevant.&lt;/p&gt;

&lt;p&gt;It’s also a fun example of how browser scripting + OpenAI API can be combined for productivity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clone repo and load unpacked in Chrome:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/anton-ds/linkedin-scraper-ext
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add your OpenAI API key and prompt in the Options page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrap-up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re curious, the code is open-source:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/anton-ds/linkedin-scraper-ext" rel="noopener noreferrer"&gt;https://github.com/anton-ds/linkedin-scraper-ext&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love feedback, ideas, or PRs!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>String + Length: A Zero-Overhead Trick in C</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Mon, 01 Sep 2025 13:39:46 +0000</pubDate>
      <link>https://forem.com/antonds/string-length-a-zero-overhead-trick-in-c-j50</link>
      <guid>https://forem.com/antonds/string-length-a-zero-overhead-trick-in-c-j50</guid>
      <description>&lt;p&gt;&lt;strong&gt;📌 Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;C&lt;/code&gt; you often need to keep a string together with its length. Calling &lt;code&gt;strlen()&lt;/code&gt; every time means extra memory scans. We want it compact and efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;✅ Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A tiny trick with typedef + macro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;sv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#define SV(s) { (s), sizeof(s) - 1 }
&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Messages&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;sv&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rep_prefix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Messages&lt;/span&gt; &lt;span class="n"&gt;mess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;SV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;SV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server reply: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After preprocessing it becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Messages&lt;/span&gt; &lt;span class="n"&gt;mess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;          &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;        &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server reply: "&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server reply: "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— string and its length, no redundant strlen().&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rep_prefix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rep_prefix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OK&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handy in network protocols, logging, binary formats — string + size always at hand, zero overhead.&lt;/p&gt;

</description>
      <category>c</category>
    </item>
    <item>
      <title>The “best stack” is a myth</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Fri, 11 Jul 2025 21:00:21 +0000</pubDate>
      <link>https://forem.com/antonds/the-best-stack-is-a-myth-192p</link>
      <guid>https://forem.com/antonds/the-best-stack-is-a-myth-192p</guid>
      <description>&lt;p&gt;There’s no universal tech stack that fits every project.&lt;br&gt;
When choosing a stack, I always focus on 3 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The task — what really needs to be done&lt;/li&gt;
&lt;li&gt;The team — who will maintain it tomorrow&lt;/li&gt;
&lt;li&gt;The context — budget, deadlines, infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes it’s Java + Kafka + Kubernetes.&lt;br&gt;
Sometimes it’s just PHP + MySQL on a basic VPS.&lt;/p&gt;

&lt;p&gt;Both can be right, if they solve the problem.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>devops</category>
    </item>
    <item>
      <title>Working on combat logic that’s completely independent of the game code</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Fri, 27 Jun 2025 22:30:47 +0000</pubDate>
      <link>https://forem.com/antonds/working-on-combat-logic-thats-completely-independent-of-the-game-code-51i5</link>
      <guid>https://forem.com/antonds/working-on-combat-logic-thats-completely-independent-of-the-game-code-51i5</guid>
      <description>&lt;p&gt;The idea is to let a designer (aka a human) create combat mechanics through an editor, which are then delivered to the game as JSON. It’s exciting to apply old knowledge to new areas like this.&lt;/p&gt;

&lt;p&gt;P.S. Spent a good while wrestling with the grid system. Eventually tracked it down to an issue with child components in the engine.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/VaF7i41duaY"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>unrealengine</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>PostgreSQL: Don't Rush to Index BOOLEAN Columns</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Mon, 23 Jun 2025 22:03:28 +0000</pubDate>
      <link>https://forem.com/antonds/postgresql-dont-rush-to-index-boolean-columns-4565</link>
      <guid>https://forem.com/antonds/postgresql-dont-rush-to-index-boolean-columns-4565</guid>
      <description>&lt;p&gt;It might feel natural to index is_active — but in PostgreSQL, it often does more harm than good.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BOOLEAN has only three values: true, false, NULL.&lt;/p&gt;

&lt;p&gt;If values are evenly distributed (e.g. 50/50), the B-tree index is inefficient. The planner will usually pick a sequential scan instead of using the index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Index helps when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One value is rare (e.g. 1% are false)&lt;/li&gt;
&lt;li&gt;Queries target only rare values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Better option: use a partial index&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_inactive&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;is_active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>postgres</category>
    </item>
    <item>
      <title>Rust for Kids</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Wed, 11 Jun 2025 22:04:41 +0000</pubDate>
      <link>https://forem.com/antonds/rust-for-kids-m0n</link>
      <guid>https://forem.com/antonds/rust-for-kids-m0n</guid>
      <description>&lt;p&gt;This article doesn’t aim to teach you Rust or unveil some hidden feature. It’s more like an experiment — a way to show a kid what Rust looks like on the inside (Rust, not the kid), rather than how to write idiomatic Rust code.&lt;/p&gt;

&lt;p&gt;In other words, devs are used to judging a language by how well it fits into their mental model of “how code should be written.” And when it doesn’t? That’s when the frustration kicks in.&lt;/p&gt;

&lt;p&gt;Here, I tried flipping the perspective — think “picture book”: how the language lives and breathes, not how we’ve learned to structure it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Disclaimer: This article isn’t about Copy types like &lt;code&gt;i32&lt;/code&gt;, &lt;code&gt;f64&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;char&lt;/code&gt;, or &lt;code&gt;&amp;amp;T.&lt;/code&gt; We're diving into move types — like String — where values are actually moved around.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alright, let’s roll.&lt;/p&gt;

&lt;p&gt;We’ll start with a core idea in Rust: a value (a memory cell) can only have one owner at a time.&lt;br&gt;
Let’s introduce a bit of “storybook” notation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;let&lt;/code&gt; = “let it be”&lt;br&gt;
&lt;code&gt;=&lt;/code&gt; = “takes ownership”&lt;br&gt;
&lt;code&gt;mut&lt;/code&gt; = “money”, yep, just a money ;)&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;let&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s let &lt;code&gt;a&lt;/code&gt; own a House:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"House"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s let &lt;code&gt;b&lt;/code&gt; own that same House. According to the rules, the previous owner has to move out — no exceptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a = {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom — error.&lt;/p&gt;

&lt;p&gt;Why? Because &lt;code&gt;a&lt;/code&gt; no longer has the right to do anything with the value (its former House). Ownership was transferred, and Rust enforces that hard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mut&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But wait — there’s more. Just owning a House doesn’t mean you can start remodeling it. Think of it like renting someone else's place — ownership without modification rights.&lt;/p&gt;

&lt;p&gt;So this will trigger an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" with Pool"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 🔴 error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to make changes, you have to buy the House with some extra money &lt;code&gt;mut&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" with pool"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// House with pool&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;c&lt;/code&gt; has the keys and the renovation permit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;amp;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can share access to the House — say, by letting a buddy crash for a while. You hand them a copy of the keys using &lt;code&gt;&amp;amp;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there’s a catch. According to the social contract, if guests are inside, no renovations allowed. The following code will throw an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" with sandbox"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// can't renovate while guests are over&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// guest is here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to wait until the guests leave:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// guest leaves&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" with sandbox"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still confused? There’s a full “guest etiquette” section at the end of the article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;amp; mut&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now let’s say your buddy wants to add a hot tub. Since that’s a modification to the House, you ask him to chip in — and in return, you give him the real keys with change privileges: &lt;code&gt;&amp;amp;mut&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" and with hot tub"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just remember: same rule applies — if someone else is holding the keys, you can’t do any remodeling. In fact, while your buddy is chilling in the hot tub, you can’t even enter the house:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" and with hot tub"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// buddy’s in the hot tub &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to wait for them to finish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" and with hot tub"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// buddy’s done&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This only applies when you gave out “paid” access (&lt;code&gt;&amp;amp;mut&lt;/code&gt;) — not when you just let someone couch-surf with &lt;code&gt;&amp;amp;.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mut &amp;amp;mut&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we rent out the House again — to another buddy, this time with full mod rights. But this buddy also has their own extra money — &lt;code&gt;mut&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" and with garden"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things are going well, and we decide to buy a second place: Apartment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Apartment"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our buddy’s not slacking either — “Let me try out the Apartment too,” he says, waving his &lt;code&gt;mut&lt;/code&gt; wallet. So he moves out of the House, into the Apartment, and starts upgrading that too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" with elevator"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same core idea: ownership with editing rights = &lt;code&gt;&amp;amp;mut&lt;/code&gt;. And declaring &lt;code&gt;let mut f&lt;/code&gt; means this buddy isn’t tied to just one location — he can move between places and make changes. Because money mut, yep&lt;/p&gt;

&lt;p&gt;After he’s gone, we end up with both properties modified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"c: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"c2: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//c: House with pool and with sandbox and with hot tub and with garden&lt;/span&gt;
&lt;span class="c1"&gt;//c2: Apartment with elevator&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: When I say “the buddy left,” I mean it literally — he’s gone, out of scope. Rust tracks that. If a variable is no longer used later in the code, Rust considers it dead — like you called &lt;code&gt;delete&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;That’s why things can seem weird: while the guest is “around,” you’re blocked from doing stuff, but it’s not always clear they’ve “left.” Rust figures it out by analyzing whether the variable is used again — if not, it’s safe to proceed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With a few rare exceptions, the same rules apply to functions too. I won’t overload this post with function examples — maybe next time :)&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ownership</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Logic Separation — One Thread per Role</title>
      <dc:creator>Anton Dolganin</dc:creator>
      <pubDate>Sun, 08 Jun 2025 17:22:14 +0000</pubDate>
      <link>https://forem.com/antonds/logic-separation-one-thread-per-role-4l3</link>
      <guid>https://forem.com/antonds/logic-separation-one-thread-per-role-4l3</guid>
      <description>&lt;p&gt;You write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kr"&gt;thread&lt;/span&gt; &lt;span class="nf"&gt;network&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serve_clients&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kr"&gt;thread&lt;/span&gt; &lt;span class="nf"&gt;game&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;game_loop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kr"&gt;thread&lt;/span&gt; &lt;span class="nf"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flush_logs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, everything still runs in sequence (depending on CPU), but the logic is cleanly separated across threads.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s way simpler than stuffing everything into one giant loop with a million &lt;code&gt;ifs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Even on a single core — this model is easier to read, test, and extend.&lt;/li&gt;
&lt;li&gt;And once you upgrade to 4+ cores — performance improves instantly, without changing the architecture.&lt;/li&gt;
&lt;li&gt;Bonus: each thread handles its own domain. Easier to reason about, debug, and scale independently&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>programming</category>
      <category>architecture</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
