<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Posts on dmitry_vk&#39;s notes</title>
		<link>https://dmitryvk.me/posts/</link>
		<description>Recent content in Posts on dmitry_vk&#39;s notes</description>
		<generator>Hugo 0.60.1 -- gohugo.io</generator>
		<language>en-us</language>
		<managingEditor>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</managingEditor>
		<webMaster>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</webMaster>
		<lastBuildDate>Wed, 24 Dec 2025 14:00:00 +0100</lastBuildDate>
		<atom:link href="https://dmitryvk.me/posts/index.xml" rel="self" type="application/rss+xml" />
		<item>
			<title>Travel Charger for my new laptop</title>
			<link>https://dmitryvk.me/posts/2025/travel-charger-for-my-new-laptop/</link>
			<pubDate>Wed, 24 Dec 2025 14:00:00 +0100</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2025/travel-charger-for-my-new-laptop/</guid>
			<description>&lt;p&gt;I recently purchased a new laptop - HP ZBook Ultra G1a 14.
It&#39;s a great laptop that has a powerful CPU/GPU, a big battery and is still light-weight.&lt;/p&gt;
&lt;div style=&#34;margin-right: 8px;&#34;&gt;&lt;img src=&#34;laptop.jpg&#34; width=&#34;600&#34; /&gt;&lt;/div&gt;
&lt;h1 id=&#34;charging-issues&#34;&gt;Charging issues&lt;/h1&gt;
&lt;p&gt;I usually don&#39;t use original laptop power supplies due to their bulkiness and general inconvenience.&lt;/p&gt;
&lt;p&gt;The new laptop is quite picky when it comes to charging it (caveat: the laptop comes in different variants with different TDPs, and variants with lower wattages might be less picky about power supply).&lt;/p&gt;
&lt;p&gt;All the laptops that I had before could be charged using a small travel-size multi-port 65W USB-C charger, which could even charge multiple device simultaneously with the laptop.
This is super convenient when traveling as I can take just one charger and use it to charge everything.&lt;/p&gt;
&lt;div style=&#34;margin-right: 8px;&#34;&gt;&lt;img src=&#34;charger-65w.jpg&#34; width=&#34;300&#34; /&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, the new laptop would not charge using any of the chargers that I had. 65W chargers did not work at all, and the 100W charger only worked in a single-port configuration.&lt;/p&gt;
&lt;p&gt;Initially I purchased a UGREEN 160W charger for around 60EUR.
Although it technically can charge the laptop, I wasn&#39;t fully satisfied with it.
The two major issues with it for me were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The charger is bulkier and heavier than I would like.&lt;/li&gt;
&lt;li&gt;Even though the total available power (160W) is more than enough for my charging needs, the way that it splits the power across its output ports is not ideal.
When connecting 3 devices, it allocates too little power to the laptop for it to start charging.
This forces me to shuffle and re-connect my devices to keep them charged.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After some research I ended up buying Anker 160W charger for around 100EUR.
Its main strengths for me were:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It is compact and lightweight.
Not as compact as 65W chargers are, but still tolerable.&lt;/li&gt;
&lt;li&gt;Power allocation across ports is not fixed and can be configured, which enables to adapt the charger to my laptop.&lt;/li&gt;
&lt;li&gt;According to tests done by others, it should be more efficient and produce less heat, though I haven&#39;t had the chance to test it out.
My previous 65W charger could get pretty warm when charging at its maximum power.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the end I am pretty happy with the Anker charger am I going to keep it.&lt;/p&gt;
&lt;h1 id=&#34;charging-experiments&#34;&gt;Charging experiments&lt;/h1&gt;
&lt;p&gt;During the course of solving the charging issues, I&#39;ve experimented with multiple chargers and collected some data.&lt;/p&gt;
&lt;h2 id=&#34;charging-in-off-state&#34;&gt;Charging in OFF state&lt;/h2&gt;
&lt;p&gt;The process of charging the laptop is very different depending on whether it&#39;s off or on.
When it&#39;s off, its battery can be charged using &lt;em&gt;any&lt;/em&gt; charger at all, even the most basic 5W (5V 1A) USB-A charger.
It would charge very slowly, but at least I know that in a pinch it&#39;s possible to charge it anywhere.
Apparently it can convert input voltage to battery voltage, so I assume that its DC-to-DC converter is too weak to be able to drive the CPU off of it.&lt;/p&gt;
&lt;h2 id=&#34;charging-in-the-on-state&#34;&gt;Charging in the ON state&lt;/h2&gt;
&lt;p&gt;After testing several chargers and several configurations of their output ports, I came to the conclusion that the only requirement is that the charger allocates at least 85W to the laptop.
If the charger has multiple port, then the port that the laptop uses must be able to provide 85W, otherwise it won&#39;t charge at all.
The laptop can use either 20V or 28V for charging (its original charger is 28V).&lt;/p&gt;
&lt;p&gt;All chargers (except for Anker) have a fixed power allocation between ports.
Anker&#39;s charger supports several modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;AI&amp;rdquo; mode, which tries to guess power requirements of each connected device&lt;/li&gt;
&lt;li&gt;C1 Priority, which allocates the largest portion of power to the first port, and the remaining power is split between ports 2 and 3&lt;/li&gt;
&lt;li&gt;Dual Laptop, which allocates 70W to first 2 ports and 20W to the remaining port&lt;/li&gt;
&lt;li&gt;Custom mode, which allows editing exactly how many watts is allocated to each port.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As far as I can see (and I confirmed it with the Anker Support), the voltages on each port are independent of each other, so it is possible to mix and match devices with different voltage requiements.&lt;/p&gt;
&lt;p&gt;The following table is a summary of the chargers and configurations I&#39;ve tried.&lt;/p&gt;
&lt;table class=&#34;charger-table&#34;&gt;
  &lt;tr&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34; colspan=&#34;2&#34;&gt;Picture&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;Charger&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34; colspan=&#34;5&#34;&gt;Port configuration&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;Outcome&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34;&gt;Mode&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34;&gt;Port 1&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34;&gt;Port 2&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34;&gt;Port 3&lt;/th&gt;
    &lt;th style=&#34;border-bottom: 1px solid;&#34;&gt;Port 4 (USB-A)&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;1&#34;&gt;
        &lt;a href=&#34;belkin-charger-65w-1.jpg&#34;&gt;&lt;img src=&#34;belkin-charger-65w-1.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;1&#34;&gt;
        &lt;a href=&#34;belkin-charger-65w-2.jpg&#34;&gt;&lt;img src=&#34;belkin-charger-65w-2.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;1&#34;&gt;Belkin 65W USB-C PD Wall Charger with PPS&lt;br&gt;Model number: WCH013vf&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;1&#34;&gt;
        &lt;a href=&#34;ugreen-charger-65w-1.jpg&#34;&gt;&lt;img src=&#34;ugreen-charger-65w-1.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;1&#34;&gt;
        &lt;a href=&#34;ugreen-charger-65w-2.jpg&#34;&gt;&lt;img src=&#34;ugreen-charger-65w-2.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;1&#34;&gt;UGREEN 65W 3-port USB-C GaN Fast Charger&lt;br&gt;Model number: X556&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;
        &lt;a href=&#34;ugreen-charger-100w-1.jpg&#34;&gt;&lt;img src=&#34;ugreen-charger-100w-1.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;
        &lt;a href=&#34;ugreen-charger-100w-2.jpg&#34;&gt;&lt;img src=&#34;ugreen-charger-100w-2.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;UGREEN 100W GaN Fast Charger&lt;br&gt;Model number: CD226&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;✅&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;
        &lt;a href=&#34;ugreen-charger-160w-1.jpg&#34;&gt;&lt;img src=&#34;ugreen-charger-160w-1.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;
        &lt;a href=&#34;ugreen-charger-160w-2.jpg&#34;&gt;&lt;img src=&#34;ugreen-charger-160w-2.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;2&#34;&gt;UGREEN 160W 4-port GaN Fast Charger&lt;br&gt;Model number: X762&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;tablet&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;✅&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;tablet&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;7&#34;&gt;
        &lt;a href=&#34;anker-charger-160w-1.jpg&#34;&gt;&lt;img src=&#34;anker-charger-160w-1.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;7&#34;&gt;
        &lt;a href=&#34;anker-charger-160w-2.jpg&#34;&gt;&lt;img src=&#34;anker-charger-160w-2.jpg&#34; width=&#34;150&#34; /&gt;&lt;/a&gt;
    &lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34; rowspan=&#34;7&#34;&gt;Anker Prime 160W, 3 ports, smart display&lt;br&gt;Model number: A2687&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&#34;AI&#34;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;tablet&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;✅&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;&#34;AI&#34;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;other laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;C1 priority&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;tablet&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;✅&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;C1 priority&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;other laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;✅&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;Dual laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;Custom, 84W&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;-&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;❌&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- mode --&gt;Custom, 85W+35W+35W&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 1 --&gt;laptop&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 2 --&gt;phone&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 3 --&gt;tablet&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;&lt;!-- port 4 --&gt;&lt;/td&gt;
    &lt;td style=&#34;border-bottom: 1px solid;&#34;&gt;✅&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;After the experiments, I&#39;ve settled on the following custom mode:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;anker-custom-profile.png&#34;&gt;&lt;img alt=&#34;anker app screenshot showing a custom mode that allocates 100W to port 1, 30W to ports 2 and 3 each&#34; src=&#34;anker-custom-profile.png&#34; width=&#34;150&#34;&gt;&lt;/a&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Some unsafe Rust tricks</title>
			<link>https://dmitryvk.me/posts/2025/some-unsafe-tricks/</link>
			<pubDate>Wed, 25 Jun 2025 00:00:00 +0200</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2025/some-unsafe-tricks/</guid>
			<description>&lt;p&gt;I&#39;m doing a hobby project in Rust and I have used a couple of &lt;code&gt;unsafe&lt;/code&gt; tricks that I&#39;d like to share.&lt;/p&gt;
&lt;h1 id=&#34;trick-1-lifetime-transmute&#34;&gt;Trick #1: Lifetime transmute&lt;/h1&gt;
&lt;p&gt;Let&#39;s imagine the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we have a struct that is shareable across threads&lt;/li&gt;
&lt;li&gt;some of struct&#39;s fields are protected by a mutex&lt;/li&gt;
&lt;li&gt;we want to lock the mutex and send the lock guard across a channel&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Normally, a lock guard has a lifetime parameter (e.g. &lt;code&gt;struct MutexGuard&amp;lt;&#39;a, T&amp;gt;&lt;/code&gt; with lifetime parameter &lt;code&gt;&#39;a&lt;/code&gt;) that is used to guarantee that the lock guard cannot outlive the lock.
The way this guarantee is enforced prevents us from sending an owned lock guard across a channel.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example of a compilation error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error[E0597]: `buf` does not live long enough
  --&amp;gt; src/main.rs:16:17
   |
13 |     let buf = Arc::new(Buffer {
   |         --- binding `buf` declared here
...
16 |     let guard = buf.data.blocking_lock();
   |                 ^^^ borrowed value does not live long enough
...
19 |         guard,
   |         ----- this usage requires that `buf` is borrowed for `&#39;static`
20 |     });
21 | }
   | - `buf` dropped here while still borrowed
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;for the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;producer&lt;/span&gt;(tx: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Sender&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;LockedBuffer&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Arc::new(Buffer&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;data: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Mutex&lt;/span&gt;::new(vec&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;[&lt;span style=&#34;color:#099&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#099&#34;&gt;2&lt;/span&gt;,&lt;span style=&#34;color:#099&#34;&gt;3&lt;/span&gt;]),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;guard&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf.data.blocking_lock();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;tx.send(LockedBuffer&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;buf: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;buf&lt;/span&gt;.clone(),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;guard,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;LockedBuffer&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;buf: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Arc&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Buffer&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;guard: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;MutexGuard&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;&amp;#39;static&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Vec&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Buffer&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;data: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Mutex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Vec&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// ....
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(&lt;a href=&#34;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=b576acfaef17484b5213c33c7ef75f92&#34;&gt;full code&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The borrow check is preventing us from doing something potentially unsafe, as it does not understand that we&#39;re packing &lt;code&gt;buf&lt;/code&gt; and &lt;code&gt;guard&lt;/code&gt; into a single struct, and &lt;code&gt;guard&lt;/code&gt; references inside &lt;code&gt;buf&lt;/code&gt;.
Rust&#39;s borrow check is just a local analysis, so it&#39;s natural that it fails to see that.&lt;/p&gt;
&lt;p&gt;We can easily work around by extending the lifetime to &lt;code&gt;&#39;static&lt;/code&gt; with &lt;code&gt;std::mem::transmute&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;guard&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf.data.blocking_lock();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// SAFETY: the `guard`&amp;#39;s referent `buf` is kept alive for the lifetime of `guard`,
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// because it&amp;#39;s stored in `LockedBuffer`, and `LockedBuffer` is not destructured.
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;guard: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;MutexGuard&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;&amp;#39;static&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;_&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::mem::transmute(guard)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;tx.send(LockedBuffer&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;buf: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;buf&lt;/span&gt;.clone(),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;guard,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(&lt;a href=&#34;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=505a0d25bed85a6a49653b68860eac46&#34;&gt;full code&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The trick works because Rust uses lifetimes only for borrow checking, and lifetimes are completely erased after borrow-checking.
That means that as long as we don&#39;t anything bad at runtime, having a &amp;ldquo;wrong&amp;rdquo; lifetime does no harm.&lt;/p&gt;
&lt;p&gt;In general, &lt;code&gt;transmute&lt;/code&gt; can be dangerous, but in this case its use is sound, since we take additional measures to ensure that the lifetime constrains between a lock and its guard are satisfied.&lt;/p&gt;
&lt;p&gt;Note that there is a &lt;a href=&#34;https://crates.io/crates/yoke&#34;&gt;&lt;code&gt;yoke&lt;/code&gt;&lt;/a&gt; crate that uses a similar technique (but is much more advanced and safe).&lt;/p&gt;
&lt;h1 id=&#34;trick-2-controlling-access-to-shared-data-with-external-locks&#34;&gt;Trick #2: controlling access to shared data with external locks&lt;/h1&gt;
&lt;p&gt;Normally, &lt;code&gt;Mutex&lt;/code&gt;es and &lt;code&gt;RwLock&lt;/code&gt;s in Rust act as containers that wrap the protected resource.
This design leads to an ergonomic and safe API, but can be restrictive at times.&lt;/p&gt;
&lt;p&gt;I have a case where I have a node-based data structure and I want to use a single lock to control access to set of fields of all nodes instead of having a mutex inside of each node.&lt;/p&gt;
&lt;p&gt;This access pattern can be implemented with &lt;code&gt;UnsafeCell&lt;/code&gt;, which requires some unsafe code around it.
In this specific case, the use of &lt;code&gt;UnsafeCell&lt;/code&gt; is pretty hard to make safe in general.
But it is still useful and can be sound.&lt;/p&gt;
&lt;p&gt;It works like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the owning struct has a lock (which will be used to control access to child nodes).
If we don&#39;t have any other state to protect, we can just add a empty unique type.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Buffers&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;lock: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Mutex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;BuffersLockToken&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;buffers: &lt;span style=&#34;color:#0086b3&#34;&gt;Vec&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Buffer&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;BuffersLockToken&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;the internal struct has an &lt;code&gt;UnsafeCell&lt;/code&gt; around the protected data:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Buffer&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;flags: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;UnsafeCell&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;we also need to implement &lt;code&gt;Sync&lt;/code&gt; for this struct (by default, &lt;code&gt;UnsafeCell&lt;/code&gt; is not shareable across threads):
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Sync&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Buffer&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;we provide method to access the resource.
The method access a reference to the lock guard for the owner to serve as an evidence that that lock is held.
This method must be unsafe as it&#39;s possible to call this method multiple times on the same instance and obtain multiple mutable references (which is UB in Rust).
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Buffer&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// SAFETY: `flags_mut` should not be called multiple times on the same `Buffer` with the same `lock_evidence`
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;flags_mut&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999&#34;&gt;self&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;_lock_evidence: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;MutexGuard&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;&amp;#39;a&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BuffersLockToken&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#008080&#34;&gt;&amp;#39;a&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u32&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// SAFETY: the access is protected by the lock on owning `Buffers`
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// this is not completely safe, but safe enough.
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#999&#34;&gt;self&lt;/span&gt;.flags.get()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;and it&#39;s used like so:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buffers&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Buffers&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;...&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;guard&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buffers.lock.blocking_lock();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;buffers.buffers[&lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;].flags_mut(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;guard)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;123&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(&lt;a href=&#34;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=77a549c55ca540f19ba53ba96b2500d5&#34;&gt;full code&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Even though this usage requires unsafe at the call site (as the user of &lt;code&gt;flags_mut&lt;/code&gt; must ensure some of the safety invariants), it is still totally worth it in my project.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>I had a wrong mental model of Rust&#39;s thread-local variables performance</title>
			<link>https://dmitryvk.me/posts/2024/rust-thread-locals-are-cheap/</link>
			<pubDate>Wed, 25 Dec 2024 23:22:00 +0200</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2024/rust-thread-locals-are-cheap/</guid>
			<description>&lt;p&gt;I had always assumed that accessing thread-local variables is somewhat expensive.
This made me reluctant to use them in my code.&lt;/p&gt;
&lt;p&gt;However, it turns out that thread-local values in practice have a similar cost of accessing them as normal global variables.&lt;/p&gt;
&lt;p&gt;I&#39;ve made a quick-and-dirty &lt;a href=&#34;https://gist.github.com/dmitryvk/306f60e7e0f958a79435f75812ab36b6&#34;&gt;benchmark&lt;/a&gt; and here are its (non-scientific) results:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bin::do_static_read: 1.28 ns/iter
bin::do_thread_static_read: 1.28 ns/iter
lib::do_static_read: 1.28 ns/iter
lib::do_thread_static_read: 1.28 ns/iter
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, this is a (probably flawed) microbenchmark, but it still shows that I should not be worrying too much about the cost of Rust&#39;s &lt;a href=&#34;https://crates.io/crates/tracing&#34;&gt;tracing&lt;/a&gt; crate (which uses thread-locals in several places).&lt;/p&gt;
&lt;p&gt;Here&#39;s the relevant disassembly (on x86-64 machine, as reported by &lt;code&gt;cargo asm&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# accessing a static variable in an executable
mov rax, qword ptr [rip + VAR]

# accessing a static variable in a library
mov rax, qword ptr [rip + VAR]

# accessing a thread-local variable in an executable
mov rax, qword ptr fs:[VAR::VAL@TPOFF]

# accessing a thread-local variable in a libary
lea rdi, [rip + VAR::VAL@TLSLD]
call __tls_get_addr@PLT
mov rax, qword ptr [rax + VAR::VAL@DTPOFF]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For static variables, Rustc was able to use PC-relative addressing mode (which is quite efficient), but thread-local variables are a bit more interesting.&lt;/p&gt;
&lt;p&gt;Apparently, thread-local storage is implemented differently when defining it in an executable or a (shared) library.
&lt;a href=&#34;https://stackoverflow.com/a/40635676&#34;&gt;This StackOverflow comment&lt;/a&gt; and &lt;a href=&#34;https://wiki.osdev.org/Thread_Local_Storage&#34;&gt;the OsDev article&lt;/a&gt; seem to have some details regarding it.
What seems to be happening is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when defining a thread-local in a binary, the compiler is able to use the &lt;code&gt;FS&lt;/code&gt; segment register to reference the thread-local area&lt;/li&gt;
&lt;li&gt;when defining a thread-local in a library, the compiler must use a less efficient way of obtaining the base address of the thread-local area via calling &lt;code&gt;__tls_get_addr&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Why the benchmark results are the same for &lt;code&gt;bin&lt;/code&gt; and &lt;code&gt;lib&lt;/code&gt;:
&lt;ul&gt;
&lt;li&gt;I think Rustc does cross-library inlining (to a certain degree), so the actual assembly being executed (after inlining) is probably a bit different than &lt;code&gt;cargo asm&lt;/code&gt; has reported&lt;/li&gt;
&lt;li&gt;If I add &lt;code&gt;#[inline(never)]&lt;/code&gt; to a function that contains the reading code, thread-local access latency increases to 1.58 ns/iter.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
		</item>
		<item>
			<title>Constructing DST pointers in Rust</title>
			<link>https://dmitryvk.me/posts/2024/make-dst-pointer/</link>
			<pubDate>Sun, 13 Oct 2024 22:37:00 +0200</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2024/make-dst-pointer/</guid>
			<description>&lt;p&gt;Recently I was working on a Rust library that implements several data structures.
One of the things I needed to do was to allocate variable-length structs. I didn&#39;t immediately find a good way to do this (even in &lt;a href=&#34;https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts&#34;&gt;Rustonomicon&lt;/a&gt;), so I think it&#39;s worth documenting how I ended up implementing it.&lt;/p&gt;
&lt;p&gt;I found some very useful hints in the code of &lt;a href=&#34;https://crates.io/crates/slice-dst&#34;&gt;slice-dst&lt;/a&gt; and &lt;a href=&#34;https://crates.io/crates/zerocopy&#34;&gt;zerocopy&lt;/a&gt; crates.&lt;/p&gt;
&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;Rust has several kinds of dynamically sized types (DSTs):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;slices: &lt;code&gt;[T]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;trait objects: &lt;code&gt;dyn Trait&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;structs that end with a DST:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;LenPrefixedBuf&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;len: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;usize&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;data: [&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;]&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this post, I&#39;ll ignore trait objects and focus on the other two kinds of DSTs:
slices and structs with slices.&lt;/p&gt;
&lt;p&gt;One way to create a pointer to a DST is to create a pointer to a statically sized type and cast it to a pointer to a compatible DST.
For my use case, this was not possible because the size of slices has to be dynamic.&lt;/p&gt;
&lt;h1 id=&#34;constructing-pointers-to-slices&#34;&gt;Constructing pointers to slices&lt;/h1&gt;
&lt;p&gt;Pointers to slices can be created using &lt;a href=&#34;https://doc.rust-lang.org/std/ptr/fn.slice_from_raw_parts.html&#34;&gt;&lt;code&gt;std::ptr::slice_from_raw_parts&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;n: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;usize&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;layout&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Layout::array::&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(n).unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;allocated: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;alloc(layout)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;slice_ptr: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;[&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;]&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;slice_from_raw_parts_mut(allocated,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;n);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;constructing-pointers-to-variablelength-structs&#34;&gt;Constructing pointers to variable-length structs&lt;/h1&gt;
&lt;p&gt;Constructing pointers to a variable-length struct is more complicated, and there is no straightforward way to do it.
There&#39;s an &lt;a href=&#34;https://rust-lang.github.io/rfcs/2580-ptr-meta.html&#34;&gt;unstable feature&lt;/a&gt; that should make it easier, but I want to avoid using unstable features unnecessarily.&lt;/p&gt;
&lt;p&gt;The way to construct a pointer is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, make a slice pointer with the address of a struct and the correct number of elements. The element type of a slice does not matter.&lt;/li&gt;
&lt;li&gt;Then cast the slice pointer to a struct pointer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This works because of the way pointer casting is specified for DSTs (see &lt;a href=&#34;https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast&#34;&gt;https://doc.rust-lang.org/reference/expressions/operator-expr.html#pointer-to-pointer-cast&lt;/a&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If T and U are both unsized, the pointer is also returned unchanged. In particular, the metadata is preserved exactly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;#[&lt;/span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;repr(C)&lt;/span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;BufWithLen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;header: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;BufWithLenHeader&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;data: [T],&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;#[&lt;/span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;repr(C)&lt;/span&gt;&lt;span style=&#34;color:#999;font-weight:bold;font-style:italic&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;BufWithLenHeader&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;len: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;usize&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufWithLen&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;layout&lt;/span&gt;(n: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;usize&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Layout&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;Layout::new::&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;BufWithLenHeader&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;.extend(Layout::array::&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(n).unwrap())&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;.unwrap()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;.&lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;.pad_to_align()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;n: &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;usize&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;layout&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufWithLen::&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;::layout(n);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;allocated: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;alloc(layout)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 1) First create pointer with the right address and the right metadata
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;dummy_slice: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;[&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;u8&lt;/span&gt;]&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;slice_from_raw_parts_mut(allocated,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;n);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// 2) Then cast pointer to the correct type
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf_ptr: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufWithLen&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;dummy_slice&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;as&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;_;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;references-to-dsts&#34;&gt;References to DSTs&lt;/h1&gt;
&lt;p&gt;A pointer can be converted to a reference by dereferencing it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;p: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;const&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;[T]&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;...;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;r: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;[T]&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;unsafe&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;p&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, the &lt;code&gt;unsafe&lt;/code&gt; block requires establishing the appropriate safety guarantees.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Using TortoiseMerge in Linux and Mac OS</title>
			<link>https://dmitryvk.me/posts/2024/tortoise-merge-wine/</link>
			<pubDate>Sat, 28 Sep 2024 19:05:00 +0200</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2024/tortoise-merge-wine/</guid>
			<description>&lt;p&gt;When I was using Tortoise SVN many years ago, I got used to its integrated merge conflict resolution tool TortoiseMerge.
Since then I have tried many other merge tools, but I still consider it to be the best.
I find that it can handle even complex merges and its merge results are very trustworthy (which I cannot say about most other merge tools).&lt;/p&gt;
&lt;p&gt;That&#39;s why I continue using it, even though it was originally only available for Windows.
With the help of Wine, it works well on Linux and Mac OS.
In this post I would like to describe how to install  and integrate it with Git.&lt;/p&gt;
&lt;h1 id=&#34;wine&#34;&gt;Wine&lt;/h1&gt;
&lt;p&gt;TortoiseMerge can be run on Linux or MacOS using Wine (which is an API compatibility layer for running Windows applications on Unix-like operating systems).&lt;/p&gt;
&lt;p&gt;Wine should be installed together with &lt;code&gt;winetricks&lt;/code&gt; (which is a set of scripts to help install Windows apps on Wine).
On Arch Linux, this can be done with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;sudo pacman -S wine winetricks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On MacOS it can be done with Homebrew:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;brew install wine
brew install winetricks
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;wine-prefix&#34;&gt;Wine prefix&lt;/h1&gt;
&lt;p&gt;Wine has a concept of &amp;ldquo;prefixes&amp;rdquo; which are isolated environments for Windows apps.
Using a separate prefix for each app ensures that applications don&#39;t affect each other, and it makes it much easier to remove apps.&lt;/p&gt;
&lt;p&gt;There is a default prefix (&lt;code&gt;~/.wine&lt;/code&gt;), but I like to make separate prefixes for every application that I run via Wine.
I usually create Wine prefixes in a per-application directory under &lt;code&gt;~/opt&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;mkdir -p ~/opt/tortoisemerge/wineprefix
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To use the prefix, the &lt;code&gt;WINEPREFIX&lt;/code&gt; environment variable should be set when running &lt;code&gt;wine&lt;/code&gt;-related commands.
This variable contains the path where the prefix should be stored.
Wine will automatically create and populate if necessary.&lt;/p&gt;
&lt;h1 id=&#34;configuring-wine&#34;&gt;Configuring Wine&lt;/h1&gt;
&lt;p&gt;I usually change some Wine&#39;s defaults right after initializing it.
I especially don&#39;t like that it defaults to 96 DPI which makes fonts too small for modern monitors.&lt;/p&gt;
&lt;p&gt;To fix it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;winecfg&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#008080&#34;&gt;WINEPREFIX&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;~/opt/tortoisemerge/wineprefix winecfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the &lt;code&gt;Graphics&lt;/code&gt; tab of the &lt;code&gt;Wine configuration&lt;/code&gt; window change the DPI to a more appropriate values. E.g., 2x scale equals 192 DPI.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;winecfg-dpi.png&#34; alt=&#34;Winecfg, graphics tab&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;installing-tortoisemerge-on-linux-and-mac-os&#34;&gt;Installing TortoiseMerge on Linux and Mac OS&lt;/h1&gt;
&lt;p&gt;The latest version of TortoiseMerge is distributed as a part of TortoiseSVN.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install some required Windows libraries that are missing from Wine:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#008080&#34;&gt;WINEPREFIX&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;~/opt/tortoisemerge/wineprefix winetricks uiribbon
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the installer from &lt;a href=&#34;https://tortoisesvn.net/downloads.html&#34;&gt;https://tortoisesvn.net/downloads.html&lt;/a&gt;. I&#39;m using the x86-64 version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install it in Wine (set the filename to the actual installer filename):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#008080&#34;&gt;WINEPREFIX&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;~/opt/tortoisemerge/wineprefix wine ~/Downloads/TortoiseSVN-1.14.7.29687-x64-svn-1.14.3.msi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will pop up the typical Windows installer, just press &amp;ldquo;Next&amp;rdquo; a couple of times.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check that everything works after installation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#008080&#34;&gt;WINEPREFIX&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;~/opt/tortoisemerge/wineprefix wine ~/opt/tortoisemerge/wineprefix/drive_c/&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Program Files&amp;#34;&lt;/span&gt;/TortoiseSVN/bin/TortoiseMerge.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The TortoiseMerge window should appear:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;tortoisemerge-initial.png&#34; alt=&#34;TortoiseMerge initial window&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;integration-with-git&#34;&gt;Integration with Git&lt;/h1&gt;
&lt;p&gt;TortoiseMerge works, now we need to tell Git to use it as a diff and merge tool.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;git config --global mergetool.tortoisemerge.cmd &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;WINEPREFIX=~/opt/tortoisemerge/wineprefix wine ~/opt/tortoisemerge/wineprefix/drive_c/&amp;#34;Program Files&amp;#34;/TortoiseSVN/bin/TortoiseMerge.exe -base &amp;#34;$BASE&amp;#34; -mine &amp;#34;$LOCAL&amp;#34; -theirs &amp;#34;$REMOTE&amp;#34; -merged &amp;#34;$MERGED&amp;#34;&amp;#39;&lt;/span&gt;
git config --global difftool.tortoisemerge.cmd &lt;span style=&#34;color:#d14&#34;&gt;&amp;#39;WINEPREFIX=~/opt/tortoisemerge/wineprefix wine ~/opt/tortoisemerge/wineprefix/drive_c/&amp;#34;Program Files&amp;#34;/TortoiseSVN/bin/TortoiseMerge.exe -mine &amp;#34;$LOCAL&amp;#34; -theirs &amp;#34;$REMOTE&amp;#34;&amp;#39;&lt;/span&gt;

git config --global merge.tool tortoisemerge
git config --global diff.tool tortoisemerge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that Git will use TortoiseMerge as a default merge and diff tool.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;tortoisemerge-merge-example.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Efficient batching</title>
			<link>https://dmitryvk.me/posts/2024/efficient-batching/</link>
			<pubDate>Thu, 25 Jan 2024 23:58:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2024/efficient-batching/</guid>
			<description>&lt;p&gt;There is a popular misconception that introducing batching sacrifices latency to improve throughput.&lt;/p&gt;
&lt;p&gt;I want to share a technique that enables batching without incurring any additional latency.
I call it the &amp;ldquo;non-blocking batching&amp;rdquo; but this name isn&#39;t super popular.&lt;/p&gt;
&lt;p&gt;I first read about it in an &lt;a href=&#34;https://www.alberton.info/batching_vs_latency_and_jobqueue_models.html&#34;&gt;article&lt;/a&gt; by Lorenzo Alberton but I haven&#39;t seen much use of this technique in the wild.&lt;/p&gt;
&lt;h1 id=&#34;batching&#34;&gt;Batching&lt;/h1&gt;
&lt;p&gt;Batching is a common technique to improve the efficiency of processing a queue of tasks.
It is performed by gathering multiple tasks into one &lt;em&gt;batch&lt;/em&gt; and processing multiple tasks at once instead of one by one.&lt;/p&gt;
&lt;p&gt;When processing tasks in a queue, there are two metrics that we care about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Throughput - How many tasks per second we can process&lt;/li&gt;
&lt;li&gt;Latency - How much time has passed between enqueueing the task and processing it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Batching improves throughput by amortizing the overhead of expensive operations that can be done once per batch instead of once per task.&lt;/p&gt;
&lt;p&gt;Examples of expensive operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;database transaction commit&lt;/li&gt;
&lt;li&gt;write to a file on a disk&lt;/li&gt;
&lt;li&gt;network request&lt;/li&gt;
&lt;li&gt;locking a mutex.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;how-batching-is-usually-done&#34;&gt;How batching is usually done&lt;/h1&gt;
&lt;p&gt;Usually, batch processing is implemented like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Wait for a new task in a queue (blocking indefinitely)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the task to a new batch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wait until a specified timeout has passed, adding new tasks to the batch&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the maximum batch size was reached before the timeout, stop waiting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Process all tasks of the batch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Loop to the beginning&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a random task distribution (governed by a Poisson random process), the batch processing looks as follows:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;slow_arrival_viz_wait.svg&#34; alt=&#34;Timeline of blocking batching&#34;&gt;&lt;/p&gt;
&lt;p&gt;On this diagram, there are two timelines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The upper timeline is the arrival of new tasks into the queue.&lt;/li&gt;
&lt;li&gt;The bottom timeline is the processing. The yellow portion represents the waiting for new tasks in the batch, green is the batch processing.&lt;/li&gt;
&lt;li&gt;Lines connect queue tasks with the batch that they were processed in.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;analysis-of-batching-efficiency&#34;&gt;Analysis of batching efficiency&lt;/h1&gt;
&lt;p&gt;We have two parameters for batching:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Maximum batch size.&lt;/p&gt;
&lt;p&gt;Batch processing time is non-linear in the batch size, and after some threshold, batching stops being effective. Limiting the batch size prevents this from happening.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Batch waiting time.&lt;/p&gt;
&lt;p&gt;Increasing batch waiting time allows more tasks to accumulate into a single batch.&lt;/p&gt;
&lt;p&gt;But simultaneously this is a wasted time that increases the latency of every task by approximately half of the batch waiting time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- # How to set the maximum batch size

It is conceptually easy to find out the right value for maximum batch size.

There are several considerations at play:

- We want to spread the fixed costs over elements of the batch. The more elements, the lower the per-element cost is
- We might have a hard limit on maximum number of elements that we may process.
- There are non-linear batch processing costs that may grow with the batch size.

We can model this as the following:

```
ProcessingTime(N) = FixedBatchCost + N * FixedElementCost + NonLinearCost(N)
```

And the per-element cost would be:

```
PerElementCost(N) = FixedBatchCost / N + FixedElementCost + NonLinearCost(N) / N
```

As `N` grows higher, the `FixedBatchCost / N` decreases.

Also, as `N` grows higher and given large enough, the `NonLinearCost(N) / N` will probably start increasing.

It means that there is a sweet sport for the most efficient batch size: it should not be too small or too large.

To properly account for all factors, we should measure the batch processing time for different batch sizes and pick the one with the lowest per-element cost. --&gt;
&lt;!-- # How to set the batch waiting time --&gt;
&lt;p&gt;Usually, the batch waiting time is set to around half of the acceptable latency or just by eyeballing it.&lt;/p&gt;
&lt;p&gt;But, counterintuitively, it is best to set this time to zero. That is, we have the following batching algorithm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Wait for a new task in a queue (blocking indefinitely)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Get up to &lt;code&gt;MaximumBatchSize&lt;/code&gt; tasks from the queue without waiting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Process the tasks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Loop back to the beginning&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s analyze the behavior of this batching in several scenarios.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Scenario 1.
The rate of arrival of new tasks is slow (much slower than processing time).
In this case, every task will be processed immediately with no additional latency.
Additional waiting time would bring no benefit and just increase the latency.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;super_slow_arrival_viz_nowait.svg&#34; alt=&#34;Visualization&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scenario 2.
Tasks arrive at regular intervals, but the average interval length is smaller than the processing time of one task.&lt;/p&gt;
&lt;p&gt;We get full utilization of processing resources with no additional latency.
The batch size automatically adapts to the speed of new tasks&amp;rsquo; arrival and the processing time.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;fast_arrival_viz_nowait.svg&#34; alt=&#34;Visualization&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scenario 3.
New tasks arrive irregularly, in bursts.
When idle, the first task of a burst gets processed immediately and the rest gets into one batch.&lt;/p&gt;
&lt;p&gt;This might be the only case when waiting might make sense since it will give a change for the entire burst to be processed as one batch.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;bursty_viz_nowait.svg&#34; alt=&#34;Visualization&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;benchmarks&#34;&gt;Benchmarks&lt;/h1&gt;
&lt;p&gt;I did a simulation of different cases and found out that the non-blocking batching beats the conventional batching every time.&lt;/p&gt;
&lt;p&gt;Here&#39;s how two batching algorithms compare in different scenarios.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Average latency with non-blocking batching&lt;/th&gt;
&lt;th&gt;Average latency with blocking batching&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Slow rate of new tasks&lt;/td&gt;
&lt;td&gt;1.55s&lt;/td&gt;
&lt;td&gt;1.94s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fast rate of new tasks&lt;/td&gt;
&lt;td&gt;5.13s&lt;/td&gt;
&lt;td&gt;7.1s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bursty new tasks&lt;/td&gt;
&lt;td&gt;2s&lt;/td&gt;
&lt;td&gt;2.06s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New tasks arrive at the same as they can be processed&lt;/td&gt;
&lt;td&gt;5.14s&lt;/td&gt;
&lt;td&gt;7.12s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We can see that in all scenarios it is better to do non-blocking batching compared to conventional blocking batching.&lt;/p&gt;
&lt;p&gt;In all cases, the following parameters were used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cost of processing: 1s per batch + 0.07 s per task in batch&lt;/li&gt;
&lt;li&gt;Batch waiting time: 0.5s&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The code for the benchmark is available at &lt;a href=&#34;https://github.com/dmitryvk/nowait-batch-modeling&#34;&gt;https://github.com/dmitryvk/nowait-batch-modeling&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The non-blocking batching is the superior batching algorithm. It gives a better latency, has fewer edge cases, and does not require complicated tuning.&lt;/p&gt;
&lt;p&gt;It should be the default when developing systems that have a queue somewhere.&lt;/p&gt;
&lt;h1 id=&#34;some-further-notes&#34;&gt;Some further notes&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Although non-blocking batching improves latency and throughput, it also in many cases increases the utilization (that is, the fraction of a time when the processor is active).
If we have a low rate of arrival of new tasks and we want to minimize the utilization of the processor, then it is beneficial to introduce artificial delays.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This batching easily generalizes to multiple workers. Each worker would do batching independently.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</description>
		</item>
		<item>
			<title>On the usefulness of topological sort</title>
			<link>https://dmitryvk.me/posts/2023/toposort/</link>
			<pubDate>Sat, 27 May 2023 21:16:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2023/toposort/</guid>
			<description>&lt;!-- # Intro --&gt;
&lt;p&gt;The topological algorithm is very useful, yet it is quite easy to understand and implement.
I&#39;ve implemented it quite frequently and want to share some of the examples where it was useful for solving practical tasks.&lt;/p&gt;
&lt;h1 id=&#34;topological-sort&#34;&gt;Topological sort&lt;/h1&gt;
&lt;p&gt;Topological sort can be defined as follows.&lt;/p&gt;
&lt;p&gt;First, we have a graph &lt;code&gt;G(V, E)&lt;/code&gt; that consists of a set of vertices &lt;code&gt;V&lt;/code&gt; and a set of edges &lt;code&gt;E&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For the purposes of the topological sort, an edge &lt;code&gt;A→B&lt;/code&gt; models a dependency of vertex &lt;code&gt;A&lt;/code&gt; on vertex &lt;code&gt;B&lt;/code&gt;.
That is, we want the processing of vertex &lt;code&gt;A&lt;/code&gt; to happen only after the processing of &lt;code&gt;B&lt;/code&gt; is completed.
The topological sort of the graph is the permutation of its vertices (i.e., every vertex must be used only) such that a vertex is listed after all its dependencies.&lt;/p&gt;
&lt;!-- Topological sort of the graph `G` is a permutation `T` of vertices `V` (that is, a sequence that contains all vertices `V` in some order) such that if there is an edge `(a, b)` in `E` then the source vertex `a` come after destination vertex `b` in the sequence `T`.
 --&gt;
&lt;p&gt;For a given graph, the topological sort might not exist (if and only if there are cyclical dependencies) or there might be many topological sorts (as is usually the case).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;fig1.svg&#34; alt=&#34;fig1&#34;&gt;&lt;/p&gt;
&lt;!-- For this graph, we have
- the set of vertices `V={1,2,3,4,5}`
- the set of edges `E={(1,3), (2, 3), (3, 4), (3, 5)}` --&gt;
&lt;p&gt;There are two possible topological sorts for this graph:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;4, 5, 3, 1, 2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5, 4, 3, 2, 1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I won&#39;t recite the algorithm here, but here are some links that have detailed descriptions of several algorithms for topological sorting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Topological_sorting&#34;&gt;https://en.wikipedia.org/wiki/Topological_sorting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cp-algorithms.com/graph/topological-sort.html&#34;&gt;https://cp-algorithms.com/graph/topological-sort.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- 
# DFS-based algorithm

A common way to implement a topological sort is by relying on DFS and keeping track whether a vertex has been visited.
It works like this:

- **Inputs**:

  - `V` - array of vertices
  - `E` - associative array from vertex to adjacency list for that vertex (i.e., list of vertices to which the current vertex has edges)

- **Temp variables**:
  - `C` - associative array from vertex to its state. Possible values of `C[v]`: `Unvisited`, `Entered`, `Exited`

- **Steps**:

  - Initialize: `C[v] := Unvisited` for each vertex `v`
  - For each vertex `v` (in any order):

    - Invoke function `DFS(v)`

- **Function DFS(v)**:

  - if `C[v] == Entered`:

    - report that a cycle was detected in the graph
    - abort
  - if `C[v] == Unvisited`:
    - `C[v] := Entered`
    - for `u` in `E[v]`:
      - invoke `DFS(u)`
    - output `v`
    - `C[v] := Exited`

The algorithm is not too complicated.
It is useful to know it since usually it is not implemented in some easy to reach libraries, in contrast with common algorithms and data structures. --&gt;
&lt;h1 id=&#34;uses-of-topological-sort&#34;&gt;Uses of topological sort&lt;/h1&gt;
&lt;p&gt;Whenever we have a task that requires ordering items or actions based on some criteria, topological sorting can be useful.
Here are some cases where I have used it in real-world projects.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Verifying the correctness of workflows in business process management software.&lt;/p&gt;
&lt;p&gt;I&#39;ve been making a workflow system in which users would edit their workflows via the GUI.&lt;/p&gt;
&lt;p&gt;Workflows consist of several steps.
Some of the steps can be performed in parallel while some are constrained to be performed one after another.
When a user finishes editing a workflow, it has to be verified that all of the steps could be completed in some order.
Topological sort of workflow steps does exactly that - if topological sort exists then the workflow is valid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Output ordering for code generation.&lt;/p&gt;
&lt;p&gt;The order of definitions and statements in generated code oftentimes matters.&lt;/p&gt;
&lt;p&gt;For example, to produce an SQL code to create tables, indices, and constraints, we have to ensure that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an index is created only after the corresponding tables and columns&lt;/li&gt;
&lt;li&gt;a foreign key constraint is created only after the corresponding tables, columns, and unique constraints&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another example is the bundling of javascript code.
Before the introduction of ES6 classes and modules, we had to rely on libraries to emulate classes.
Class definitions using those libraries were inherently order-dependent: class could only be defined after its superclass was defined.
This necessitates ordering bundled modules in the order of topological sorting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Code initialization order&lt;/p&gt;
&lt;p&gt;I was designing a modular system that loads and initializes plugins and modules.
The initialization of a module could invoke components provided by another module and register its components, as well as do some side effects.
This means that modules depend on each other, and the order of module initialization is specified by the dependencies of modules.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Type inference in nested data queries&lt;/p&gt;
&lt;p&gt;In several BI systems, we have let users define custom data queries that could refer to other data queries.
To infer the types of result data table columns, queries had to be processed in the order specified by their interdependencies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Database migrations&lt;/p&gt;
&lt;p&gt;I was designing a database migration framework for a larger framework for building web apps.
It was designed for modularity: web apps are composed of modules (some are pre-built, some are custom-built) built by different teams.&lt;/p&gt;
&lt;p&gt;The framework was designed with one big shared database in mind, and each module was responsible for its own set of tables in the shared database.
To manage changes to the database schema, we employed migrations but quickly ran into the problem of ordering the execution of migrations.
The complexity of database schema management was exacerbated by the concurrency of development: different teams released versions of their modules on different schedules without too much coordination.&lt;/p&gt;
&lt;p&gt;Since all modules were in the same database, they executed DDL statements (such as &lt;code&gt;CREATE TABLE&lt;/code&gt; or &lt;code&gt;ALTER TABLE&lt;/code&gt;) or DML statements (such as &lt;code&gt;INSERT INTO&lt;/code&gt; or &lt;code&gt;UPDATE&lt;/code&gt;) that referred to the tables owned by other modules.
Essentially, each migration is required to be executed before or after some other migrations (that created or dropped the corresponding tables or columns).&lt;/p&gt;
&lt;p&gt;By specifying this ordering in the migration itself, we could then find an appropriate order for database migrations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;issues-with-topological-sort&#34;&gt;Issues with topological sort&lt;/h1&gt;
&lt;p&gt;Some fine points must be considered when employing topological sort:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When a graph contains a cycle, the toposort algorithm just gives up.
But in some cases, we want to process the graph anyway, even if some parts of it cannot be sorted&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The topological sort definition is ambiguous. A graph may have multiple topological sorts.
This issue comes in two dimensions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Different algorithms may produce different order&lt;/li&gt;
&lt;li&gt;Subtle changes in the graph may produce drastically different topological order&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
		</item>
		<item>
			<title>Programming contests are good for me (and probably for you too)</title>
			<link>https://dmitryvk.me/posts/2023/programming-contests-are-good/</link>
			<pubDate>Sat, 06 May 2023 23:31:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2023/programming-contests-are-good/</guid>
			<description>&lt;h1 id=&#34;criticism-of-programming-contests&#34;&gt;Criticism of programming contests&lt;/h1&gt;
&lt;p&gt;I have come across numerous instances of criticism of competitive programming and programming contests.
To summarize, the criticism boils down to these points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Competition-style tasks during job interviews are the wrong way to filter candidates;&lt;/li&gt;
&lt;li&gt;Competitive programming does not give a relevant experience in software engineering;&lt;/li&gt;
&lt;li&gt;Competitive programming is detrimental to software engineering work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I must say upfront that I agree with the first point.
The problems that are used in programming contests are quite different from the tasks that are normally encountered in day-to-day work.&lt;/p&gt;
&lt;p&gt;But it is the other points that I want to address.
Programming contests give a lot of skills and experience that are usually quite hard to obtain elsewhere. The programming contests were transformative for my programming skills.&lt;/p&gt;
&lt;h1 id=&#34;typical-structure-of-a-contest&#34;&gt;Typical structure of a contest&lt;/h1&gt;
&lt;p&gt;Programming contests are designed to test and challenge the skills of designing and implementing algorithms.
They are relatively short timewise (usually around 5 hours).
In some contests, teams compete while in others individuals do.&lt;/p&gt;
&lt;p&gt;During the contest, the participants are offered a small number of problem statements to solve.
Participants may solve tasks in any order.&lt;/p&gt;
&lt;h2 id=&#34;a-problem-statement&#34;&gt;A problem statement&lt;/h2&gt;
&lt;p&gt;A problem statement is a non-ambiguous description of a task to solve.&lt;/p&gt;
&lt;p&gt;The solution to the problem is a source code for a program that reads input data (that describes a specific instance of a problem) from &lt;code&gt;STDIN&lt;/code&gt; and outputs the solution &lt;code&gt;STDOUT&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The time and memory that the solution may use are limited.
The constraints on time and memory are always present in the problem statement.
Since time and memory are constrained, the problem statements also include limits on possible input data such as the number of elements, maximum values for numeric values, and so on.&lt;/p&gt;
&lt;p&gt;The problem statement also includes several instances of input data with the correct corresponding output data (collectively called &amp;ldquo;a test case&amp;rdquo;) to serve as examples.&lt;/p&gt;
&lt;h2 id=&#34;scoring-and-submissions&#34;&gt;Scoring and submissions&lt;/h2&gt;
&lt;p&gt;Having coded the solution, a participant submits it for grading.
The grading is automated and the result is available in a short time (usually in about a minute).
The grading system compiles the source code and runs the program on many test cases and checks its output.
The result of a run on some test is either &amp;ldquo;OK&amp;rdquo;, &amp;ldquo;Wrong Answer&amp;rdquo;, &amp;ldquo;Runtime Error&amp;rdquo;, &amp;ldquo;Time Limit Exceeded&amp;rdquo; or &amp;ldquo;Memory Exceeded&amp;rdquo; (result names are self-explanatory).
In case of a failure, the participant will only know the number of the first failing test case without any other specifics.&lt;/p&gt;
&lt;p&gt;There are 2 distinct methods to score solutions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If the solution passes all tests, it gets a score.&lt;/p&gt;
&lt;p&gt;The time to solve is also taken into account. So the participants are ranked  first by the number of solved tasks (or by the sum of scores) and then by the sum of submission times.
Many competitions, including the ACM ICPC, use this scoring style.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each passed test case gains some amount of score.&lt;/p&gt;
&lt;p&gt;This style is not as popular, though some beginner-friendly competitions do use such a style.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;the-specific-skills-that-contests-help-level-up&#34;&gt;The specific skills that contests help level up&lt;/h1&gt;
&lt;p&gt;Here&#39;s a list of skills that are required for successful participation in a programming competition.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Data Structures and Algorithms&lt;/p&gt;
&lt;p&gt;This is the obvious one.&lt;/p&gt;
&lt;p&gt;The problems are primarily designed to practice the knowledge of algorithms and the skill to combine them or invent new ones on the spot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Attention to Details&lt;/p&gt;
&lt;p&gt;Many problems and algorithms have numerous edge cases that must not be missed.
Sometimes a tiny detail might mean a difference between either a trivial or a very complicated algorithm.&lt;/p&gt;
&lt;p&gt;All participants are trained to read the task descriptions carefully and not miss any important details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Selection of appropriate algorithm based on the scale and complexity of a problem.&lt;/p&gt;
&lt;p&gt;Oftentimes it is possible to solve a problem using either of several different algorithms, and one needs to pick an appropriate algorithm.
It takes a certain skill to be able to pick an algorithm based on a task description.
Some factors that affect algorithm selection are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The ease of the implementation of an algorithm.&lt;/p&gt;
&lt;p&gt;It makes no sense to use an advanced algorithm (or a data structure) when a simpler one would do.
The complexity theory, big-O notation together with some well-known scale constants help here.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Time and memory constraints, input size, and specifics of the input data.&lt;/p&gt;
&lt;p&gt;The bigger the input size, the more efficient the algorithm has to be.&lt;/p&gt;
&lt;p&gt;The amount of memory and time that the algorithm takes depends on the size of an input (e.g., number of elements in the input), limits on numeric values (e.g., this is very important for dynamic programming algorithms), or some properties of an input (e.g., the number of distinct values, number of graph components, presence of cycles, etc.).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Algorithm assumptions and special properties of input data.&lt;/p&gt;
&lt;p&gt;Some algorithms may only be applied if an input satisfies some criteria.
E.g., Dijkstra&#39;s algorithm won&#39;t work on graphs with negative edges, and heap-based algorithms won&#39;t work if we need to preserve the order of elements.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thorough testing of code and algorithms&lt;/p&gt;
&lt;p&gt;The strict grading procedure quickly teaches to only submit tested solutions, since the code that has not been thoroughly tested does not have a chance to be accepted.&lt;/p&gt;
&lt;p&gt;Since the tasks and algorithms are quite complex, manual example-based testing does not suffice, and more advanced testing techniques are required.&lt;/p&gt;
&lt;p&gt;Some of the commonly employed techniques are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;randomized and property-based testing&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;assertions for the invariants&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;oracle-based testing. Some common oracles are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;alternative (usually more trivial) implementation of an algorithm&lt;/li&gt;
&lt;li&gt;generating the input data together with the correct answer or in such a way the correct answer is known&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Staying focused in high-stress conditions&lt;/p&gt;
&lt;p&gt;Competitions are always stressful.
Contests can be quite intense, especially when the time is running out.&lt;/p&gt;
&lt;p&gt;It is natural to do &amp;ldquo;shotgun debugging&amp;rdquo; when under stress, i.e. non-systematically trying some random ideas without first acquiring an understanding of the nature of the bug in hopes that it fixes the bug. Instead, we must be methodical and keep using proven working techniques since there is no other way.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;how-the-structure-of-contests-helps-acquire-skills&#34;&gt;How the structure of contests helps acquire skills&lt;/h1&gt;
&lt;h2 id=&#34;rapid-feedback&#34;&gt;Rapid feedback&lt;/h2&gt;
&lt;p&gt;We learn and gain experience by doing something and seeing if it works or not.
This requires that the feedback loop is quick and gives good and actionable feedback.&lt;/p&gt;
&lt;p&gt;The feedback loop in competitions is orders of magnitude faster and more precise compared to typical software engineering projects.
Commercial software projects are lengthy.
It might take months or years to see all the latent bugs that may be lurking in the codebase.
Competitions provide near-instantaneous feedback - one quickly learns to test the code and which testing techniques are quick and reliable.&lt;/p&gt;
&lt;p&gt;Commercial projects are long, complicated, and have a lot of parts and participants.
It might be hard to learn from experience on real-world projects since:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It usually takes a significant time for the code to get from a developer to exercising in production of all the functionality including the edge cases
One may even not work on this project anymore.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mistakes are costly.&lt;/p&gt;
&lt;p&gt;Therefore projects have a lot of redundancy and fail-safety mechanisms that mask some problems in the software.&lt;/p&gt;
&lt;p&gt;It is very beneficial for real-world software to have mechanisms such as retries, self-healing, and periodic reboots.
But for education, the software should fail loudly and explicitly &amp;ndash; so we can learn not to make the same mistakes again.&lt;/p&gt;
&lt;p&gt;In programming competitions, such solutions simply won&#39;t be accepted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It is hard to attribute the success or failure of a project to specific parts of the software or to the work of specific individuals or teams.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;strict-solutions-checking-with-tight-time-and-memory-constraints&#34;&gt;Strict solutions checking with tight time and memory constraints&lt;/h2&gt;
&lt;p&gt;The test suites for problems have very good coverage and it is almost unbelievable how well they can find bugs and flaws in solutions.&lt;/p&gt;
&lt;p&gt;It is virtually impossible to have a buggy or inefficient solution accepted since the grading system checks correctness and efficiency.&lt;/p&gt;
&lt;h2 id=&#34;hiding-of-failed-tests-penalties-for-failing-submissions&#34;&gt;Hiding of failed tests, penalties for failing submissions&lt;/h2&gt;
&lt;p&gt;Since a participant does not see the failing test case, the attempts to brute-force the solution are infeasible.&lt;/p&gt;
&lt;p&gt;Penalties for faulty submissions encourage participants to not rely on any provided tests.
Instead, participants must implement their own testing.
Since the contest time is limited, this testing must also be effective and must not take too much time.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Based on all of the above,&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;competitive programming is not the same as real-world software engineering;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nonetheless, the training for programming competitions can immensely improve some of the software engineering skills;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To learn efficiently, it is very useful to have good feedback loops.&lt;/p&gt;
&lt;p&gt;The faster and more accurate they are, the easier it is to learn. Contests offer good feedback loops for some of the kills, for some of which there are a few alternatives.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</description>
		</item>
		<item>
			<title>How to implement async stream in Rust without resorting to macros</title>
			<link>https://dmitryvk.me/posts/2023/async-stream-without-macros/</link>
			<pubDate>Sat, 07 Jan 2023 10:35:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2023/async-stream-without-macros/</guid>
			<description>&lt;p&gt;I published the &lt;a href=&#34;https://crates.io/crates/async-fn-stream&#34;&gt;&lt;code&gt;async-fn-stream&lt;/code&gt;&lt;/a&gt; crate which is a lightweight alternative to &lt;a href=&#34;https://crates.io/crates/async-stream&#34;&gt;&lt;code&gt;async-stream&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;async-iteration&#34;&gt;Async iteration&lt;/h1&gt;
&lt;p&gt;Rust provides support for async iteration via the &lt;a href=&#34;https://docs.rs/futures/latest/futures/stream/trait.Stream.html&#34;&gt;&lt;code&gt;Stream&lt;/code&gt;&lt;/a&gt; trait.
It allows to decouple producer of data from the consumer,
just like an &lt;a href=&#34;https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html&#34;&gt;&lt;code&gt;Iterator&lt;/code&gt;&lt;/a&gt; allows the same for blocking code.
This is immensely useful if the producer is expected to produce a large (or infinite) sequence.&lt;/p&gt;
&lt;p&gt;Both &lt;code&gt;Stream&lt;/code&gt; and &lt;code&gt;Iterator&lt;/code&gt; are quite easy to use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// Iterator
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;x&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;in&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;produce_iter()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;println&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;{x}&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;produce_iter&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Iterator&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Item&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;...&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;// Stream
&lt;/span&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;stream&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;produce_stream().await;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;pin_mut&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;(stream);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;while&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Some&lt;/span&gt;(x)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;stream.next().await&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;println&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;{x}&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;produce_stream&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Stream&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Item&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;i32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;...&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can see that the usage of &lt;code&gt;Stream&lt;/code&gt; has somewhat more boilerplate code but it&#39;s still quite OK. Most likely Rust will in the future gain language support for using &lt;code&gt;Stream&lt;/code&gt;s in &lt;code&gt;for&lt;/code&gt; loops.&lt;/p&gt;
&lt;!-- # Implementation of iterator and streams

Currently, it&#39;s no too ergonomic to hand-code implementations of either `Stream` or `Iterator`.
One has to implement the `Iterator::next()` or `Stream::poll_next()` method that might sometimes be cumbersome to implement.
For example, here&#39;s how we can implement the iterator over rows for blocking IO (ignore the fact that it&#39;s already implemented in `BufRead::lines()`):

```rust
use std::{
    fs::File,
    io::{BufRead, BufReader},
    path::Path,
};

struct LinesIter&lt;B: BufRead&gt; {
    file: B,
}

fn read_lines(path: &amp;Path) -&gt; std::io::Result&lt;LinesIter&lt;BufReader&lt;File&gt;&gt;&gt; {
    let file = File::open(path)?;
    let file = BufReader::new(file);
    Ok(LinesIter { file })
}

impl&lt;B: BufRead&gt; Iterator for LinesIter&lt;B&gt; {
    type Item = std::io::Result&lt;String&gt;;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        let mut line = String::new();
        match self.file.read_line(&amp;mut line) {
            Ok(0) =&gt; None,
            Ok(_) =&gt; Some(Ok(line)),
            Err(error) =&gt; Some(Err(error)),
        }
    }
}
```

You can see the code is still pretty readable for blocking version and it&#39;s .
But the async version is much trickier -- I could not write it in any satisfactory way. --&gt;
&lt;h1 id=&#34;the-asyncstream-crate&#34;&gt;The &lt;code&gt;async-stream&lt;/code&gt; crate&lt;/h1&gt;
&lt;p&gt;Currently, it&#39;s not too ergonomic to hand-code implementations of either &lt;code&gt;Stream&lt;/code&gt; or &lt;code&gt;Iterator&lt;/code&gt;.
The &lt;code&gt;Iterator::next()&lt;/code&gt; method might sometimes be cumbersome to implement, but usually, it&#39;s doable without too much effort.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;Stream::poll_next()&lt;/code&gt; is much harder to implement.
Often this necessitates storing (and swapping) futures inside of &lt;code&gt;Stream&lt;/code&gt; implementation struct which is quite hard to do without unsafe code.
To tackle this issue, Tokio team has written a great crate &lt;a href=&#34;https://crates.io/crates/async-stream&#34;&gt;&lt;code&gt;async-stream&lt;/code&gt;&lt;/a&gt; which I recommend checking out.&lt;/p&gt;
&lt;p&gt;This macro lets us create an async stream with ease:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::path::Path;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;async_stream::stream;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;futures::{pin_mut,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Stream,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;StreamExt};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;tokio::{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;fs::File,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;io::{AsyncBufReadExt,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufReader},&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;read_lines&lt;/span&gt;(path: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Path&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;std&lt;/span&gt;::io::&lt;span style=&#34;color:#0086b3&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Stream&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Item&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::io::&lt;span style=&#34;color:#0086b3&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;File::open(path).await&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;?&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufReader::new(file);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;stream&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;String&lt;/span&gt;::new();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;buf.clear();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file.read_line(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf).await&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(&lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;break&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(_)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(buf.clone()),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Err&lt;/span&gt;(error)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Err&lt;/span&gt;(error),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(result)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And it even runs and provides correct output!&lt;/p&gt;
&lt;h1 id=&#34;why-i-dont-like-to-use-asyncstream-in-production-code&#34;&gt;Why I don&#39;t like to use &lt;code&gt;async-stream&lt;/code&gt; in production code&lt;/h1&gt;
&lt;p&gt;So, is the problem solved?
Maybe so, but for me, unfortunately, this solution leaves a lot to be desired.&lt;/p&gt;
&lt;p&gt;And I must say upfront that this is not a fault of &lt;code&gt;async-stream&lt;/code&gt; - those are general problems associated with macros in Rust.
&lt;code&gt;async-stream&lt;/code&gt; just makes it more apparent because &lt;code&gt;stream! { ... }&lt;/code&gt; often encompasses large chunks of code.&lt;/p&gt;
&lt;p&gt;Let&#39;s look closely at this code.&lt;/p&gt;
&lt;p&gt;The first that I notice is that &lt;code&gt;rustfmt&lt;/code&gt; does not even try to reformat the code inside &lt;code&gt;stream!&lt;/code&gt; macro.
For example, if I mess up the formatting of this code like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;stream&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;String&lt;/span&gt;::new();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                    &lt;/span&gt;buf.clear();&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file.read_line(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf).await&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(&lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;break&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(_&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;   &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(buf.clone()),&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Err&lt;/span&gt;(error)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;yield&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Err&lt;/span&gt;(error),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;then &lt;code&gt;rustfmt&lt;/code&gt; will leave this code as-is.
And if you use &lt;code&gt;rustfmt --check&lt;/code&gt; in the CI pipeline to ensure that formatting stays consistent, it also won&#39;t notice any inconsistencies in formatting.&lt;/p&gt;
&lt;p&gt;The second and much more important downside is that some features of the IDE do not work as well as they should.
Here&#39;s what happens if I try to use autocomplete in Visual Studio Code with rust-analyzer:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;rust-analyzer-async-stream.png&#34; alt=&#34;rust-analyzer autocompletion for code inside stream! macro&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;an-alternative-to-asyncstream&#34;&gt;An alternative to &lt;code&gt;async-stream&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Having found this solution unsatisfactory for my needs, I went ahead and published my take on it. Meet the &lt;a href=&#34;https://crates.io/crates/async-fn-stream&#34;&gt;&lt;code&gt;async-fn-stream&lt;/code&gt;&lt;/a&gt; crate.&lt;/p&gt;
&lt;p&gt;It&#39;s the same idea as &lt;code&gt;async-stream&lt;/code&gt; but implemented without resorting to macros.&lt;/p&gt;
&lt;p&gt;Here&#39;s what the code looks like and the summary of differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;async_stream::stream! { ... }&lt;/code&gt; is replaced with &lt;code&gt;async_fn_stream::fn_stream(|emitter| async move { ... })&lt;/code&gt; (there&#39;s also a &lt;code&gt;try_fn_stream&lt;/code&gt; which is similar to &lt;code&gt;try_stream!&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yield X&lt;/code&gt; is replaced with &lt;code&gt;emitter.emit(X).await&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::path::Path;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;async_fn_stream::fn_stream;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;futures::{pin_mut,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Stream,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;StreamExt};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;tokio::{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;fs::File,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;io::{AsyncBufReadExt,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufReader},&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;read_lines&lt;/span&gt;(path: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;Path&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;std&lt;/span&gt;::io::&lt;span style=&#34;color:#0086b3&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Stream&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Item&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::io::&lt;span style=&#34;color:#0086b3&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;File::open(path).await&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;?&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;BufReader::new(file);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;fn_stream(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;|&lt;/span&gt;emitter&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;move&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;String&lt;/span&gt;::new();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;buf.clear();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;file.read_line(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;buf).await&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(&lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;break&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(_)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;emitter.emit(&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(buf.clone())).await,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Err&lt;/span&gt;(error)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;emitter.emit(&lt;span style=&#34;color:#0086b3&#34;&gt;Err&lt;/span&gt;(error)).await,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;(result)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, code completion works fine:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;rust-analyzer-async-fn-stream.png&#34; alt=&#34;rust-analyzer autocompletion for code inside normal function macro&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you&#39;ve also tried using &lt;code&gt;async-stream&lt;/code&gt; and met similar issues, I recommend checking my crate out.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Small example of async GUI code with Gtk-rs: alert() function</title>
			<link>https://dmitryvk.me/posts/2020/gtkrs-async-alert-example/</link>
			<pubDate>Sun, 29 Mar 2020 20:29:45 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2020/gtkrs-async-alert-example/</guid>
			<description>&lt;p&gt;Let&#39;s suppose that I want to write the following function in Rust with Gtk-rs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#d14&#34;&gt;/// Display the message in the dialog window and wait for it to be dismissed by the user.
&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;alert&lt;/span&gt;(title: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;str&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;text: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;str&lt;/span&gt;);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After some experimentation, I found that one good way to implement such a function is to use one-shot channels.
Currently, &lt;code&gt;futures&lt;/code&gt; crate &lt;a href=&#34;https://docs.rs/futures/0.3.4/futures/channel/oneshot/index.html&#34;&gt;provides them&lt;/a&gt;
on stable releases &amp;mdash; so I&#39;ll use those. Note that Rust&#39;s async ecosystem still evolves and things might change in the future.&lt;/p&gt;
&lt;p&gt;Oneshot channels are created with &lt;a href=&#34;https://docs.rs/futures/0.3.4/futures/channel/oneshot/fn.channel.html&#34;&gt;&lt;code&gt;oneshot::channel()&lt;/code&gt;&lt;/a&gt; function
and have two ends: sender and receiver.
The key property is that &lt;em&gt;the receiver end is a &lt;code&gt;Future&lt;/code&gt;&lt;/em&gt;. We will use this to build our functions.&lt;/p&gt;
&lt;p&gt;In this article, I&#39;ll walk us through the implementation of &lt;code&gt;alert()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;That&#39;s a function epilogue and some &lt;code&gt;use&lt;/code&gt;&#39;s which we&#39;ll need later. Note that the function is declared as async
which means that it actually returns an anonymous implementation of &lt;code&gt;Future&amp;lt;Output=()&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#d14&#34;&gt;/// Display the message in the dialog window and wait for it to be dismissed by the user.
&lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;alert&lt;/span&gt;(title: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;str&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;text: &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;gtk::prelude::&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;*&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::rc::Rc;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::cell::RefCell;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;futures::channel::oneshot::channel&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;as&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;oneshot_channel;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We will need a channel that will hold the result of our function. Since the result is an empty unit value,
this channel will act as an event or barrier on which further code will wait.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(result_sender,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result_receiver)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;oneshot_channel();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we will have to deal with some memory management details. Here are a few important facts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.rs/futures/0.3.4/futures/channel/oneshot/struct.Sender.html#method.send&#34;&gt;&lt;code&gt;oneshot::Sender::send()&lt;/code&gt;&lt;/a&gt; method consumes &lt;code&gt;Self&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Gtk-rs&#39;s accepts bare &lt;code&gt;Fn(&amp;amp;Self)&lt;/code&gt; functions as callbacks
(e.g., see &lt;a href=&#34;https://docs.rs/gtk/0.8.1/gtk/trait.DialogExt.html#tymethod.connect_response&#34;&gt;DialogExt.connect_response&lt;/a&gt;).
These may be potentially called multiple times and hence they capture their environments as immutable &lt;code&gt;&amp;amp;&lt;/code&gt;-borrows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two facts combined together means that we need to wrap &lt;code&gt;result_sender&lt;/code&gt; in several wrappers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Option&lt;/code&gt;. We will use &lt;code&gt;Option::take()&lt;/code&gt; method to be able to consume the sender&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RefCell&lt;/code&gt;. Since our callback is an &lt;code&gt;Fn()&lt;/code&gt;, the captured environment is immutable and we need interior mutability to be able to send into the channel.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Rc&lt;/code&gt;. &lt;code&gt;result_sender&lt;/code&gt; will be shared between our main async stack frame and callback.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result_sender&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Rc::new(RefCell::new(&lt;span style=&#34;color:#0086b3&#34;&gt;Some&lt;/span&gt;(result_sender)));&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we are ready to build our UI widget.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;dialog&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;gtk::MessageDialogBuilder::new()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.buttons(gtk::ButtonsType::&lt;span style=&#34;color:#0086b3&#34;&gt;Ok&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.message_type(gtk::MessageType::Info)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.text(text)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.modal(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;true&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.title(title)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.type_(gtk::WindowType::Toplevel)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.build();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we should attach handler for &lt;a href=&#34;https://developer.gnome.org/gtk3/stable/GtkDialog.html#GtkDialog-response&#34;&gt;&lt;code&gt;response&lt;/code&gt; signal&lt;/a&gt; which is emitted
when user responds to dialog (e.g., by closing it or by click on &lt;code&gt;OK&lt;/code&gt; button). In our case, we don&#39;t care what was the user&#39;s response - we just
need to known when user dismissed the dialog.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Rc&lt;/code&gt; with the sender is cloned; in this case, it&#39;s not strictly necessary, but in general, it is usually required to clone objects that go
into callback&#39;s captured environment.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result_sender2&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result_sender.clone();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;dialog.connect_response(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;move&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;|&lt;/span&gt;_,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;response&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the &lt;code&gt;response&lt;/code&gt; signal handler, we need to notify the channel that we are done. First we unwrap all layers of wrappers and then send the unit value into the channel.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;println&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;!&lt;/span&gt;(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Response={}&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;response);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result_sender&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;result_sender2.borrow_mut().take().unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;result_sender.send(()).unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the signal handler is connected, we should show the dialog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;dialog.show_all();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then we await from the receiver end of the channel. Since we are awaiting &lt;em&gt;asynchronously&lt;/em&gt;, Gtk+ event loop keeps processing events &lt;em&gt;concurrently&lt;/em&gt; while we are waiting.
And that&#39;s very important &amp;mdash; otherwise, our dialog which we just created would not be able to show itself on a screen and accept user input.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;result_receiver.await.unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After the &lt;code&gt;response&lt;/code&gt; signal, the dialog window will stay open and be visible to the user. We need to close the window with &lt;code&gt;.destroy()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: Gtk+ terminology of &lt;code&gt;close&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt; is pretty confusing. I&#39;ve had to re-read documentation and examples multiple times to double-check my code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;dialog.destroy();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The dialog window now is not displayed but the corresponding Gtk+ object still exists. Rust&#39;s RAII (&lt;code&gt;Drop&lt;/code&gt;) will clean it up automatically at this point.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, we just need to run this function. The current version of Gtk-rs has all the necessary pieces to run async GUI code.&lt;/p&gt;
&lt;p&gt;The following code will initialize Gtk+ and then run async code to completion and then will quit the program.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;ui_main&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;alert(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Message&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Hello, world&amp;#34;&lt;/span&gt;).await;&lt;span style=&#34;color:#bbb&#34;&gt;    
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;gtk::init().expect(&lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;Failed to initialize Gtk+&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;glib::MainContext::default().spawn_local(async&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;move&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;ui_main().await;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;gtk::main_quit();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;gtk::main();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: Some time ago I released a &lt;a href=&#34;https://crates.io/crates/gtk-future-executor&#34;&gt;gtk-future-executor crate&lt;/a&gt; which could be used to execute the future on Gtk+ event loop.
This crate should be considered obsolete.&lt;/p&gt;
&lt;p&gt;The whole example is available &lt;a href=&#34;https://gist.github.com/dmitryvk/9ce63c7114d9a4eb570b0292ec4ef813&#34;&gt;as a gist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: this post was written assuming the following versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gtk-rs 0.8.1&lt;/li&gt;
&lt;li&gt;Async-std 1.5.0&lt;/li&gt;
&lt;li&gt;Glib-rs 0.9.3&lt;/li&gt;
&lt;li&gt;futures 0.3.4&lt;/li&gt;
&lt;/ul&gt;
</description>
		</item>
		<item>
			<title>Notes on guaranteed shutdown of test containers</title>
			<link>https://dmitryvk.me/posts/2019/test-container-shutdown/</link>
			<pubDate>Sun, 08 Dec 2019 03:15:07 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2019/test-container-shutdown/</guid>
			<description>&lt;p&gt;One use for containers is to provision dependencies for automated software testing.&lt;/p&gt;
&lt;p&gt;This approach is supported by at least several libraries for several languages. These libraries are usually easy to set up and easy to use.&lt;/p&gt;
&lt;p&gt;Usually, one would start the container in &lt;code&gt;setUp&lt;/code&gt; and stop the container in &lt;code&gt;tearDown&lt;/code&gt;. This approach usually works fine but it does one quite big drawback: &lt;strong&gt;if a test crashes then you leak the container&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In my prior experiences with provisioning dependencies for automated tests, it is very easy to exhaust resources when debugging tests or when tests fail to clean up after themselves. I believe that tests should be as robust as possible so I find this situation unacceptable.&lt;/p&gt;
&lt;p&gt;I had not seen any mention of this in documentation so I decided to share what I use to prevent this issue.&lt;/p&gt;
&lt;p&gt;I had tried different techniques to overcome this issue and I had settled on the following technique:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;All containers are started with &lt;code&gt;autoremove&lt;/code&gt; option to ensure that storage is cleaned up when the container is stopped.
But this is not enough - we need to ensure that the container will actually be stopped.&lt;/li&gt;
&lt;li&gt;When the container starts, the watchdog is injected which monitors whether there is an active user of the container.&lt;/li&gt;
&lt;li&gt;If watchdog detects that test software has unexpectedly disconnected from container then it forcibly terminates the container.&lt;/li&gt;
&lt;li&gt;One of the easy and robust ways of implementing watchdog is the following:
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A shell script is injected into a running container that reads from standard input until it is closed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# this loop will keep running while tests are attached to the container&lt;/span&gt;
&lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# when docker detects client disconnect the loop will be terminated&lt;/span&gt;
&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#0086b3&#34;&gt;read&lt;/span&gt; VAR; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;do&lt;/span&gt;
  true;
&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;done&lt;/span&gt;;

&lt;span style=&#34;color:#0086b3&#34;&gt;kill&lt;/span&gt; -9 &lt;span style=&#34;color:#099&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;# or some other command that will terminate the container&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Background task inside the test process starts and attaches to the injected script.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This reliably ensures that tests don&#39;t leave unused containers behind.&lt;/p&gt;
&lt;p&gt;Some container management libraries do not even try solve this issue (e.g., popular .NET library &lt;a href=&#34;https://github.com/testcontainers/testcontainers-dotnet&#34;&gt;TestContainers-dotnet&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://testcontainers.org&#34;&gt;TestContainers&lt;/a&gt; (a java library) uses different approach for ensuring guaranteed shutdown and release of all used resources. It starts a separate container (called &lt;code&gt;ryuk&lt;/code&gt;) and establishes persistent connection to it; &lt;code&gt;ryuk&lt;/code&gt; then uses this connection to monitor presence of its client. I haven&#39;t used it extensively, but apparently it works really well. Note that this is not mentioned in &lt;code&gt;TestContainers&lt;/code&gt;&amp;rsquo; documentation and I even missed this very important feature on my first review of such libraries.&lt;/p&gt;
&lt;p&gt;(Updated on 2019-12-19 to mention &lt;code&gt;ryuk&lt;/code&gt;)&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Why Rust instead of C&#43;&#43;</title>
			<link>https://dmitryvk.me/posts/2017/why-rust-no-cpp/</link>
			<pubDate>Fri, 17 Nov 2017 22:13:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2017/why-rust-no-cpp/</guid>
			<description>&lt;p&gt;The talk &lt;a href=&#34;https://www.youtube.com/watch?v=lkgszkPnV8g&#34;&gt;Curiously Recurring C++ Bugs at Facebook&lt;/a&gt; by Louis Brandy at CppCon 2017 demonstrates several examples of when Rust might be better than C++.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>ICFPC 2012 is coming</title>
			<link>https://dmitryvk.me/posts/2012/icfpc-2012-is-coming/</link>
			<pubDate>Tue, 03 Apr 2012 23:36:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2012/icfpc-2012-is-coming/</guid>
			<description>&lt;p&gt;I can&#39;t help but note that &lt;a href=&#34;http://icfpconference.org/icfp2012/&#34;&gt;ICFPC is due to start on the 13th of July&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Notes on threads and spaghetti code</title>
			<link>https://dmitryvk.me/posts/2012/notes-on-threads-and-spaghetti-code/</link>
			<pubDate>Mon, 13 Feb 2012 23:45:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2012/notes-on-threads-and-spaghetti-code/</guid>
			<description>&lt;p&gt;Recently there were a lot of talks going along the lines of &amp;ldquo;threads and blocking code is bad and callbacks-based asynchrony is good&amp;rdquo;.&lt;/p&gt;
&lt;h1 id=&#34;tldr&#34;&gt;TL;DR&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;event-driven concurrency is pretty much equivalent to thread-based concurrency&lt;/li&gt;
&lt;li&gt;it is possible to implement threads with a low overhead&lt;/li&gt;
&lt;li&gt;threads allow writing natural sequential code&lt;/li&gt;
&lt;li&gt;therefore threads are more useful than asynchrony based on events and callbacks&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;a-little-bit-of-theory&#34;&gt;A little bit of theory&lt;/h1&gt;
&lt;p&gt;Both synchronous blocking computation processes and async non-blocking computation processes have some state associated with them. For example, for an HTTP server that state might contain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;network socket and associated kernel resources&lt;/li&gt;
&lt;li&gt;buffer in userspace for socket IO&lt;/li&gt;
&lt;li&gt;HTTP protocol parser state&lt;/li&gt;
&lt;li&gt;HTTP headers and body&lt;/li&gt;
&lt;li&gt;HTTP request body parser state&lt;/li&gt;
&lt;li&gt;response buffer&lt;/li&gt;
&lt;li&gt;other state that is necessary for HTTP handler state (e.g., state and buffer for database query processing)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This state is always present independent of the style that the code is written in - whether it uses callbacks or is represented as a state machine or if it&#39;s sequential blocking code running in its own thread.&lt;/p&gt;
&lt;p&gt;Proponents of some fashionable and hyped technologies sometimes present the idea that the only way to write &amp;ldquo;web scale&amp;rdquo; apps is to ditch threads and blocking calls, and switch to a style that I call &amp;ldquo;callback spaghetti&amp;rdquo;. A more formal name for &amp;ldquo;callback spaghetti&amp;rdquo; is the continuation-passing style. Transforming code to CPS (continuation-passing style) is a mechanical task, but when done manually it becomes quite tedious and error-prone and it also balloons the size of the code.&lt;/p&gt;
&lt;p&gt;Continuation-passing style by passing into each function a callback which is to be called by the inner function the result is available.
Furthermore, composing functions involves composing callbacks.
It is possible to see that the resulting callback chain is equivalent to a call stack, albeit represented as a linked list instead of a contiguous array.&lt;/p&gt;
&lt;p&gt;My argument for sequential code running in separate threads is as follows: such sequential code is easier to read, and flow control structures are implemented more or less easily. Such code is more reliable since there are simple and reliable mechanisms for error handling; there are exceptions; stack traces contain useful information; it is easier to ensure the timely release of resources.&lt;/p&gt;
&lt;h1 id=&#34;in-practice&#34;&gt;In practice&lt;/h1&gt;
&lt;p&gt;The main argument against thread-based concurrency is that threads occupy a lot of resources, hence we can&#39;t create too many of them.
For native threads this might be true: they have relatively large creation overhead, they occupy a significant amount of memory for stack (usually several megabytes) and thread-local storage, and they have a lot of overhead for context switching. But OS-native threads are just one way to implement threads: threads can be implemented with lower overhead.&lt;/p&gt;
&lt;p&gt;Let&#39;s consider Linux glibc threads as an example.
Here&#39;s what is contained inside a thread:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;per-thread OS task scheduler state inside a kernel&lt;/li&gt;
&lt;li&gt;stack space&lt;/li&gt;
&lt;li&gt;CPU context (saved CPU and FPU registers)&lt;/li&gt;
&lt;li&gt;signal mask&lt;/li&gt;
&lt;li&gt;thread return value&lt;/li&gt;
&lt;li&gt;synchronization objects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main areas of overhead for such threads are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;thread switching always happens from the OS kernel, i.e. for each thread switch there is a transition from userspace to kernel and back. This is bad for performance if such switches happen often&lt;/li&gt;
&lt;li&gt;thread scheduler, depending on its implementation, might visibly slow down if the number of threads gets too large&lt;/li&gt;
&lt;li&gt;threads have quite a large stack by default - around several megabytes. In my opinion, this is the main reason why we cannot have too many native threads.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;POSIX defines several means to manage contexts and switch them - &lt;code&gt;makecontext&lt;/code&gt;, &lt;code&gt;getcontext&lt;/code&gt;, &lt;code&gt;setcontext&lt;/code&gt;, &lt;code&gt;swapcontext&lt;/code&gt;. A context in POSIX contains the entire thread state except for kernel objects. With the help of the contexts, we can make our own threads. Such threads that are created in userspace are called green threads. When using green threads, we have to provide the stack memory ourselves. This lets us have control over and minimize memory usage by threads.&lt;/p&gt;
&lt;p&gt;The largest downside of POSIX contexts is that a context also contains the signal mask which entails a syscall to change it in order to maintain context switch semantics defined by POSIX. Oftentimes we don&#39;t have a particular need to manage a signal mask. If we implement &lt;code&gt;swapcontext&lt;/code&gt; manually (which would take us a dozen of assembly instructions per CPU architecture) then the overhead would reduce significantly.&lt;/p&gt;
&lt;p&gt;As a simple optimization, we can skip saving unused CPU registers. As a further optimization, we could employ liveness analysis to avoid saving local variables that are not used while a thread is not being scheduled.&lt;/p&gt;
&lt;p&gt;In conclusion, the usage of green threads allows us to write the same good old straightforward sequential code and at the same time have a lot of threads running. For this reason, I much prefer using green threads for network IO-related tasks and native OS threads for everything else.&lt;/p&gt;
&lt;p&gt;See also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Continuation-passing_style&#34;&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Continuation-passing_style&#34;&gt;http://en.wikipedia.org/wiki/Continuation-passing_style&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Operating Systems: Design and Implementation. Andrew Tanenbaum&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://usenix.org/events/hotos03/tech/full_papers/vonbehren/vonbehren_html/&#34;&gt;Why Events Are A Bad Idea for high-concurrency servers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.stanford.edu/class/cs240/readings/threads-bad-usenix96.pdf&#34;&gt;Why Threads Are A Bad Idea&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://webcrunch.ru/library/development/highload-basics/kak-pisat-visokoproizvoditelnie-servera/&#34;&gt;Антон Самохвалов. Как писать высокопроизводительные сервера.&lt;/a&gt; (In Russian)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PS[0]. In node.js ecosystem there is a &lt;code&gt;node-fibers&lt;/code&gt; package. It uses the &lt;code&gt;libcoroutine&lt;/code&gt; underhood to implement lightweight threads on V8 engine which somewhat alleviates the callback spaghetti problem.&lt;/p&gt;
&lt;p&gt;PS[1]. Erlang is a great example of what green threads are capable of. Green threading allows it to have hundreds of thousands of lightweight processes on a single machine.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Looking for a new maintainer for CL-GTK2</title>
			<link>https://dmitryvk.me/posts/2011/looking-for-maintainer-clgtk2/</link>
			<pubDate>Wed, 02 Feb 2011 09:09:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2011/looking-for-maintainer-clgtk2/</guid>
			<description>&lt;p&gt;I haven&#39;t been writing anything for Lisp for some time, and my projects are slowly getting unmaintained.
Cl-gtk2 is one of them, unfortunately.
But I would hate to see cl-gtk2 stop evolving since it is truly useful.&lt;/p&gt;
&lt;p&gt;That&#39;s why I&#39;m looking for someone who would take cl-gtk2 from me and keep maintaining it. I would provide any kind of support if necessary.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SBCL-1.0.45 with Windows threads</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-1.0.45-windows-threads/</link>
			<pubDate>Sun, 19 Dec 2010 23:40:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-1.0.45-windows-threads/</guid>
			<description>&lt;p&gt;I&#39;ve merged the patch from Anton Kovalenko to use TLS slot 63. There was some minor hiccup - I merged one commit but totally missed the next commit in the series and lost some trying to untie the know.&lt;/p&gt;
&lt;p&gt;I&#39;ve then reabased my branch onto SBCL-1.0.45 and published the binary to &lt;a href=&#34;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.45-threads.msi&#34;&gt;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.45-threads.msi&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Couple of words regarding FS:0x14</title>
			<link>https://dmitryvk.me/posts/2010/more-on-fs0x14/</link>
			<pubDate>Sun, 21 Nov 2010 09:20:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/more-on-fs0x14/</guid>
			<description>&lt;p&gt;The Apache Harmony JVM on Win32 also uses the Arbitrary Data slot of TIB (&lt;a href=&#34;http://harmony.apache.org/subcomponents/drlvm/doxygen/thread/html/hythread_8h.html#a1d1769fa5bae8d6787012140835c0fe&#34;&gt;link&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;And also this slot is used as a TLS pointer in a GML library (OpenGL Multithreading Library) inside the Spring project (Sprint is a game engine that can run games such as Total Annihilation).&lt;/p&gt;
</description>
		</item>
		<item>
			<title>A useful article on codegen techniques</title>
			<link>https://dmitryvk.me/posts/2010/some-codegen-techniques/</link>
			<pubDate>Tue, 16 Nov 2010 10:32:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/some-codegen-techniques/</guid>
			<description>&lt;p&gt;I&#39;ve stumbled upon a reference to the article &lt;a href=&#34;http://www.daimi.au.dk/dOvs/slides/46b-codegeneration-in-V8.pdf&#34;&gt;One-pass Code Generation in V8&lt;/a&gt; in &lt;code&gt;mr-aleph&lt;/code&gt;&#39;s &lt;a href=&#34;http://mr-aleph.livejournal.com/301011.html&#34;&gt;post&lt;/a&gt; (though it&#39;s more of a slide deck than an article).
I found the article to be quite good regarding both the contents and the style.
It describes the code generation architecture that employs several techniques to generate code without &amp;ldquo;silly&amp;rdquo; instruction sequences such as &lt;code&gt;push eax; pop eax;&lt;/code&gt; without the use of peephole optimizations but instead by providing more information to code generation routines for primitive operations.&lt;/p&gt;
&lt;p&gt;At first sight, this looks quite similar to the code generation architecture of the SBCL compiler.&lt;/p&gt;
&lt;p&gt;It is a pure joy to study using articles like that.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>cl-sqlite-0.2 released</title>
			<link>https://dmitryvk.me/posts/2010/cl-slite-0_2/</link>
			<pubDate>Mon, 15 Nov 2010 06:45:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/cl-slite-0_2/</guid>
			<description>&lt;p&gt;I&#39;ve released the new version 0.2 of cl-sqlite.&lt;/p&gt;
&lt;p&gt;I&#39;ve added support for named parameters in queries. For error signaling, now &lt;code&gt;sqlite-error&lt;/code&gt; class is used instead of &lt;code&gt;cl:error&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The link to the new version: &lt;a href=&#34;http://common-lisp.net/project/cl-sqlite/releases/cl-sqlite-0.2.tar.gz&#34;&gt;http://common-lisp.net/project/cl-sqlite/releases/cl-sqlite-0.2.tar.gz&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SBCL 1.0.44 with Windows threads</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-1_0_44-windows-threads/</link>
			<pubDate>Sat, 06 Nov 2010 23:39:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-1_0_44-windows-threads/</guid>
			<description>&lt;p&gt;I&#39;ve updated the &lt;code&gt;windows-threads&lt;/code&gt; branch to SBCL-1.0.44. Installer is available at &lt;a href=&#34;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.44-threads-1.msi&#34;&gt;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.44-threads-1.msi&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SBCL Windows threads implementation notes, part 2</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-windows-threads-impl-notes-2/</link>
			<pubDate>Fri, 05 Nov 2010 22:28:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-windows-threads-impl-notes-2/</guid>
			<description>&lt;h1 id=&#34;suspension&#34;&gt;Suspension&lt;/h1&gt;
&lt;p&gt;Thread suspension is implemented via safepoints. Safepoint is implemented with a read of the special memory location (&amp;lsquo;GC poll address&amp;rsquo; which is located in &amp;lsquo;GC poll page&amp;rsquo;).&lt;/p&gt;
&lt;p&gt;In the first phase, the &amp;lsquo;master&amp;rsquo; thread unmaps the GC poll page. After this, other threads will at some time get page faults. Several issues must be dealt with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The reaction to unmapping is not immediate - the thread must reach the safepoint&lt;/li&gt;
&lt;li&gt;Some threads will not reach safepoint soon (if a thread is executing foreign code or a blocking system call)&lt;/li&gt;
&lt;li&gt;Even if a thread has reached a safepoint, it does not mean that GC can start. The thread may be inside a WITHOUT-GCING section, for example. In this case, the thread may not be resumed with the GC poll page unmapped.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can draw some conclusions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Every thread that can reach safepoint (if it&#39;s not in foreign code or in blocking syscall) must reach it before GC can proceed.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Every thread that can not reach safepoint must not interfere with GC if it suddenly returns to a lisp code&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After all the threads have reached safepoint, we must wait for all threads to be ready for GC.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This implies the two-phase suspension.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Phase 1:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;GC poll page is remapped as unreadable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The master thread checks each thread: if it&#39;s running lisp code, wait until it reaches a safepoint. Thread is considered to reach a safepoint when its state is STATE_SUSPENDED_BRIEFLY.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Phase 2:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;GC poll page is mapped again so that threads can run until they are ready for GC&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The master thread waits for every thread to be ready for GC. This is achieved by waiting for the state of every thread to become STATE_SUSPENDED (except for threads that are ready for GC)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thread is ready for GC if:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;thread_state(thread) == STATE_SUSPENDED; or&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;thread_is running foreign code and it is not inside WITHOUT-GCING or WITHOUT-INTERRUPTS, and blockable signals are unblocked&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For this, the thread-local variable &lt;code&gt;*GC-SAFE*&lt;/code&gt; is introduced - it tracks the current readiness for GC of a thread. It is guaranteed that when &lt;code&gt;*GC-SAFE*&lt;/code&gt; changes from NIL to T, the thread checks if GC is in progress and enters the suspended state.&lt;/p&gt;
&lt;h1 id=&#34;thread-interruption&#34;&gt;Thread interruption&lt;/h1&gt;
&lt;p&gt;Thread interruption is similar, but we don&#39;t need to wait for all threads to reach a safepoint - it is only necessary for the interrupted thread to reach a safepoint.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Phase 1:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The GC poll page is remapped as unreadable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The master thread checks interrupted thread: if it&#39;s running lisp code, wait until it reaches a safepoint. Thread is considered to reach a safepoint when its state is STATE_SUSPENDED_BRIEFLY.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Phase 2:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;GC poll page is mapped&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;All threads that have reached a safepoint are released&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;safepoint-code&#34;&gt;Safepoint code&lt;/h1&gt;
&lt;p&gt;The safepoint code is called to check whether the thread has something to do related to SBCL internal working. It is called:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;When a thread reaches a safepoint and the GC poll page is unmapped&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When leaving and entering a foreign code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On other occasions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Safepoints have several responsibilities.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If there is a GC or thread interruption in progress, the thread has to notify the master thread that it has reached a safepoint. Safepoint does this by changing the state to STATE_SUSPENDED_BRIEFLY and waiting for the state to be changed by the master thread. When it resumes, the thread checks whether it should suspend or interrupt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If a thread should suspend, it is checked whether it can be suspended. If thread is suspendable, it changes its state to STATE_SUSPENDED; otherwise, it sets STOP_FOR_GC_PENDING (and sets pseudo_atomic_interrupted)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If a thread should interrupt, it either sets INTERRUPT_PENDING and pseudo_atomic_interrupted or executes interruption.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If GC is pending and the thread can do GC, it runs the GC&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If an interrupt is pending and a thread can execute it, the thread executes it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On some occasions, the runtime is in a very fragile state and can not really do anything that safepoint must do (e.g., change thread state, execute GC, execute interruption). These are e.g. using lisp thread synchronization primitives. To control this, the &lt;code&gt;*DISABLE-SAFEPOINTS*&lt;/code&gt; variable is used.&lt;/p&gt;
&lt;p&gt;GC code is run inside a safepoint, and safepoint code is not reentrable. GC code itself has safepoints (since SUB-GC is a normal lisp function, it calls lisp synchronization routines and does several switches to/from foreign code). To prevent the reentering of a safepoint code, the &lt;code&gt;*IN-SAFEPOINT* &lt;/code&gt;variable is used.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Some manuals are factually wrong</title>
			<link>https://dmitryvk.me/posts/2010/wrong-manuals/</link>
			<pubDate>Thu, 04 Nov 2010 17:49:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/wrong-manuals/</guid>
			<description>&lt;p&gt;I&#39;ve bought a new Logitech mouse, and the manual for it says this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Horizontal scrolling (feature may depend on software). This function is not available on Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;But the funn thing is that it works without a hitch.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SBCL Windows threads implementation notes, part 1</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-windows-threads-implementation-notes-1/</link>
			<pubDate>Thu, 04 Nov 2010 14:08:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-windows-threads-implementation-notes-1/</guid>
			<description>&lt;p&gt;Since I&#39;ve Windows threads patches to SBCL for review, I&#39;m publishing my implementation notes.&lt;/p&gt;
&lt;h1 id=&#34;threadlocal-storage&#34;&gt;Thread-local storage&lt;/h1&gt;
&lt;p&gt;For each thread, Windows allocates a Thread Information Block
(&lt;a href=&#34;http://en.wikipedia.org/wiki/Win32_Thread_Information_Block&#34;&gt;ref. 1&lt;/a&gt;, &lt;a href=&#34;http://www.microsoft.com/msj/archive/s2ce.aspx&#34;&gt;ref. 2&lt;/a&gt;, &lt;a href=&#34;http://msdn.microsoft.com/en-us/library/aa232399(VS.60).aspx&#34;&gt;ref. 3&lt;/a&gt;). Thread can access its own Thread Information Block through the FS register (e.g., &lt;code&gt;%FS:0&lt;/code&gt; is the first field in TIB). TIB contains frequently used thread-specific data such as Last Error Number, pointer to SEH (structured exception handling) frame, thread id, and TLS backing store. This structure is documented in &lt;a href=&#34;http://www.microsoft.com/msj/archive/s2ce.aspx&#34;&gt;ref. 2&lt;/a&gt; and &lt;a href=&#34;http://www.microsoft.com/msj/archive/s2cea.htm&#34;&gt;ref. 4&lt;/a&gt;. TIB has an &amp;lsquo;Arbitrary&amp;rsquo; field which is described as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;14h DWORD pvArbitrary&lt;/code&gt; field is theoretically available for applications to use however they want. It&#39;s almost like an extra thread-local storage slot for you to use, although I&#39;ve never seen an application use it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This sound just like what is needed for implementing thread-local storage - a memory location that we can freely use and that is easily accessible. Unfortunately, there is a possibility that some libraries would also use this field for their purposes (and there are examples of such libraries). And when some other conflicting code will run, it will be hard to detect this.&lt;/p&gt;
&lt;p&gt;So clearly, a better way of storing the TLS pointer is needed. TIB also contains the first 64 slots for Windows thread-local storage. There are several options for implementing TLS with that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Windows allows executables to preallocate TLS slots. We can take, e.g., TLS slot 0, and all access to lisp&#39;s TLS will go through TLS at a fixed offset. But it would somewhat complicate the initialization of lisp runtime and the build process.&lt;/li&gt;
&lt;li&gt;We can grab some other fixed slot number by successively allocating TLS slots (TlsAlloc) until we get the slot we want. After that, we free the slots we allocated that we don&#39;t need. This way, we can use TLS slot 63 and lisp&#39;s TLS pointer will be at a known offset. It is quite safe to use this slot; libraries on Windows commonly use no more than one TLS slot (and &amp;lsquo;system&amp;rsquo; libraries don&#39;t even use TLS - they have their own fields in TIB).&lt;/li&gt;
&lt;li&gt;We can allocate the TLS slot in a normal Windows way and store it in a global variable. This way, we don&#39;t need to do any weird things, but TLS access will have one more indirection. This would further complicate SBCL&#39;s TLS access because macros and code generation assume that TLS does not require any indirection. This is the best way to go but it requires more changes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Currently, TLS is implemented as option 2. On initialization, we take slot 63 (or fail if we couldn&#39;t - but I can&#39;t imagine the situation where this can happen). When the &lt;code&gt;windows-threads&lt;/code&gt; branch will be merged to SBCL, we should consider option 3 because if implemented now, the change would be more than necessary for Windows threading support.&lt;/p&gt;
&lt;p&gt;TLS notes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;This only applies to Win32. Win64 is very different&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clozure CL, on the other hand, uses ES segment register and undocumented Win32 functions to allocate a segment and store it in a segment register. This is problematic because WOW64 (the Windows subsystem to run Win32 applications in Windows 64) does not preserve the value of ES register during context switches (including thread preemption). This is the reason why the 32-bit version of Clozure CL does not work on Windows 64.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;thread-suspension-and-interruption&#34;&gt;Thread suspension and interruption&lt;/h1&gt;
&lt;p&gt;Lisp code in SBCL runs in a managed environment &amp;ndash; SBCL needs to be able to safely suspend threads (because it uses the stop-the-world garbage collector) and interrupt them (i.e., call some function in a specific thread).&lt;/p&gt;
&lt;p&gt;On Unix-like systems, suspending and interrupting threads is simple (but correctly synchronizing threads and writing code that is tolerable to asynchronous interruptions is not simple). This is achieved by using POSIX signals.&lt;/p&gt;
&lt;p&gt;Windows API, on the other hand, does not provide equivalent asynchronous interruptions. They have to be emulated. I&#39;ll list several ways of emulating them:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&amp;lsquo;Thread hijacking&amp;rsquo;. Windows lets stop a thread, examine its context, modify it, and restart a thread. This way, another thread may modify the stack and registers in such a way that thread will execute some other function and then return to where it was.&lt;/p&gt;
&lt;p&gt;This might seem to be the way to emulate signals, but it is not. This is racy with Windows internals in several ways (&lt;a href=&#34;http://translate.google.com/translate?js=n&amp;amp;prev=_t&amp;amp;hl=en&amp;amp;ie=UTF-8&amp;amp;layout=2&amp;amp;eotf=1&amp;amp;sl=ru&amp;amp;tl=en&amp;amp;u=http://blog.not-a-kernel-guy.com/2010/05/04/812&#34;&gt;ref. 5&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;QueueUserAPCEx. Windows has support for Asynchronous Procedure Calls (APCs), but only &amp;lsquo;kernel APCs&amp;rsquo; can interrupt a thread when it is in user mode. &amp;lsquo;kernel APCs&amp;rsquo; are available from drivers and there is the QueueUserAPCEx project (&lt;a href=&#34;http://www.codeproject.com/KB/threads/QueueUserAPCEx_v2.aspx&#34;&gt;ref. 6&lt;/a&gt;) that provides support for them.&lt;/p&gt;
&lt;p&gt;This has a very big drawback in that it requires a kernel-mode driver to be installed to function correctly. Because of that, I haven&#39;t tried it. By the way, the pthreads_win32 (&lt;a href=&#34;http://sourceware.org/pthreads-win32/&#34;&gt;ref. 7&lt;/a&gt;) project uses QueueUserAPCEx if it&#39;s available.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thread polling. Thread periodically checks if it should suspend or interrupt. This does not require any special support from an operating system. But it requires injecting polling into the code and to tolerate potentially infinite delays (they may occur when a thread executes a blocking operation).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Among the noted approaches, the only one that really works is the last one. So it&#39;s clear that we have no other choice but to implement polling in SBCL threads. Luckily, I didn&#39;t even need to do this myself &amp;ndash; Paul Khuong implemented &amp;lsquo;gc safepoints&amp;rsquo; for SBCL (&lt;a href=&#34;http://www.pvk.ca/Blog/LowLevel/VM_tricks_safepoints.html&#34;&gt;ref. 8&lt;/a&gt;, &lt;a href=&#34;http://repo.or.cz/w/sbcl/pkhuong.git/shortlog/refs/heads/gc-safe-points&#34;&gt;ref. 9&lt;/a&gt;). The safepoints are implemented by reading a specific memory location and discarding the result (e.g., with &lt;code&gt;test %eax, GC_POLL_PAGE_ADDR&lt;/code&gt; instruction). In normal conditions, this instruction will not affect the running code. But if the memory page is read-protected or unmapped, this will cause an exception and we will land in the exception handler where we can analyze what has happened and what to do next.&lt;/p&gt;
&lt;p&gt;In the next post, I&#39;ll write about how threads are synchronized for timely suspension and interruption.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SBCL 1.0.43 with Windows threads</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-1_0_43-windows-threads/</link>
			<pubDate>Sat, 30 Oct 2010 05:59:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-1_0_43-windows-threads/</guid>
			<description>&lt;p&gt;I&#39;ve rebased the Windows threads branch against the current version of SBCL: &lt;a href=&#34;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.43-threads-g002bdc7.msi&#34;&gt;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.43-threads-g002bdc7.msi&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Some linguistic discoveries</title>
			<link>https://dmitryvk.me/posts/2010/linguistic-discoveries/</link>
			<pubDate>Thu, 30 Sep 2010 22:22:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/linguistic-discoveries/</guid>
			<description>&lt;p&gt;Sometimes I ponder whether inaccurate use of terminology causes us to misunderstand things as our perception is distorted by various associations.&lt;/p&gt;
&lt;p&gt;For example, there is the term &amp;ldquo;pattern&amp;rdquo;. It is used in different contexts, and two uses are particularly useful - &amp;ldquo;design pattern&amp;rdquo; and &amp;ldquo;pattern recognition&amp;rdquo;. In Russian, this term is usually translated as &amp;ldquo;шаблон&amp;rdquo; which literally means &amp;ldquo;template&amp;rdquo;. Being a Russian, I&#39;ve gotten used to perceiving this term as a &amp;ldquo;template&amp;rdquo; and I believe that had caused me to not understand properly several papers.&lt;/p&gt;
&lt;p&gt;But then it dawned on me that &amp;ldquo;pattern&amp;rdquo; rather means &amp;ldquo;закономерность&amp;rdquo; (&amp;ldquo;pattern&amp;rdquo;) instead of &amp;ldquo;шаблон&amp;rdquo; (&amp;ldquo;template&amp;rdquo;). A template is an object that defines the properties of other objects, while a template is an object that represents the properties of other objects.&lt;/p&gt;
&lt;p&gt;And the weird thing is that dictionaries don&#39;t always help to properly understand words. For example, Lingvo translates the term &amp;ldquo;pattern&amp;rdquo; in pretty much the same way - as a &amp;ldquo;template&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;As far as I can see, it&#39;s not just me that is susceptible to such biases. For example, the title of the famous GoF book &amp;ldquo;Design Patterns&amp;rdquo; is translated into Russian as &amp;ldquo;Шаблоны проектирования&amp;rdquo; (&amp;ldquo;Design Templates&amp;rdquo;) rather than &amp;ldquo;Закономерности проектирования&amp;rdquo; (&amp;ldquo;Design Patterns&amp;rdquo;) or &amp;ldquo;Часто используемые приемы проектирования&amp;rdquo; (&amp;ldquo;Common Design Techniques&amp;rdquo;). And I believe that this perpetuated the belief that the GoF book is about some ready-to-use templates for software architecture or rules to be followed to get a good architecture.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SBCL 1.0.42 with Windows threads</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-1_0_42-windows-threads/</link>
			<pubDate>Sat, 25 Sep 2010 15:31:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-1_0_42-windows-threads/</guid>
			<description>&lt;p&gt;I&#39;ve rebased my patches for Windows threading against SBCL 1.0.42 and made a release: &lt;a href=&#34;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.42-threads.msi&#34;&gt;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.42-threads.msi&lt;/a&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Alpha version of SBCL with Windows threads is ready for testing</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-1_0_40-alpha/</link>
			<pubDate>Thu, 16 Sep 2010 22:07:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-1_0_40-alpha/</guid>
			<description>&lt;p&gt;I&#39;ve published a new binary build of SBCL with Windows threads support at &lt;a href=&#34;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.40-threads-2.msi&#34;&gt;https://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.40-threads-2.msi&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I would greatly appreciate it if you would run the tests on your machines (the tests that I&#39;ve used for debugging are at &lt;a href=&#34;http://gist.github.com/582848&#34;&gt;http://gist.github.com/582848&lt;/a&gt;) and report back the results.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>The tale of one deadlock in SBCL on Windows</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-vs-win32/</link>
			<pubDate>Wed, 15 Sep 2010 12:48:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-vs-win32/</guid>
			<description>&lt;p&gt;I keep discovering new bugs.&lt;/p&gt;
&lt;p&gt;I recently finished the debugging session which took several weeks of my time. The SBCL process was hanging while loading cl-gtk2 from SLIME. But this hanging magically fixed itself if I would type anything into the &lt;code&gt;*inferior-lisp*&lt;/code&gt; Emacs buffer, after which the loading would continue without any troubles. If I loaded cl-gtk2 from the console, all would go well.&lt;/p&gt;
&lt;p&gt;At first, I was blaming it on some kind of a deadlock somewhere deep inside SBCL. I&#39;ve tried various options for printing debug logs but it all did not help.&lt;/p&gt;
&lt;p&gt;Normal native debuggers are unable to debug Lisp code in SBCL since SBCL uses interrupt instructions (&lt;code&gt;int 3&lt;/code&gt;) to process interrupts, and debuggers just keep stopping all the time. Although recent SBCL versions gained the support for using &lt;code&gt;UD2&lt;/code&gt; instruction which is not supported to break inside the debugger. The only thing to help debug was a stack trace of all threads at the moment of a hang. Of course, native stack traces are useless for debugging Lisp code so I didn&#39;t even know in which of the high-level code did the hang happen.&lt;/p&gt;
&lt;p&gt;By bisecting over cl-gtk2 code I could find the code that hung - which was a call to the &lt;code&gt;gtk-init-check&lt;/code&gt; function. When the hang happened, the stack trace contained a call to &lt;code&gt;GdiPlus.dll!__DllMainCRTStartup&lt;/code&gt; which had called &lt;code&gt;kernel32.dll!_LoadLibraryExW&lt;/code&gt;. This suggested to me that the hang was due to the loading of a &lt;code&gt;GdiPlus.dll&lt;/code&gt; dynamic library.&lt;/p&gt;
&lt;p&gt;To check this hypothesis, I&#39;ve run SBCL from the console, and the call &lt;code&gt;(load-shared-object &amp;quot;GdiPlus.dll&amp;quot;)&lt;/code&gt; completes without errors, but in REPL it hangs.&lt;/p&gt;
&lt;p&gt;The hang itself happened inside the &lt;code&gt;GetFileType&lt;/code&gt; function. MSDN documentation for it is quite harmless:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Retrieves the file type of the specified file.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What instead was usable is the comment inside MSDN that &lt;code&gt;GetFileType&lt;/code&gt; can sometimes hang. Searching on the web for &lt;code&gt;GetFileType hangs&lt;/code&gt; reveals this nugget:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For instance, GetFileType on a pipe &lt;em&gt;hangs&lt;/em&gt; if there is a pending read request, which, BTW, causes the DLL load to hang sometimes since the C runtime startup in the DLL calls GetFileType on all known handles while setting up the file descriptor table for open/fopen.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, I&#39;m used to documentation being quite spotty (especially when it comes to Microsoft documentation), but it&#39;s impossible to prepare for something like this in advance.&lt;/p&gt;
&lt;p&gt;Fortunately, this bug is not caused by my code and that means that I&#39;m ready to publish the SBCL fork with Windows threads for wider testing.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>More fixes for SBCL on Windows</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-impl-misc-notes/</link>
			<pubDate>Sun, 18 Jul 2010 15:17:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-impl-misc-notes/</guid>
			<description>&lt;p&gt;Apparently, I still haven&#39;t nailed down the thread suspension for SBCL.&lt;/p&gt;
&lt;p&gt;Some newly discovered problems are related to calling a Lisp code from the C function &lt;code&gt;funcall&lt;/code&gt;.
The thread state was changing incorrectly: thread enters Lisp code which means that the &lt;code&gt;gc_flag&lt;/code&gt; should be unset, but it is not the case.
And then the garbage collector skips such a thread and keeps on collecting the garbage while the mutator thread is doing its own business.
Obviously, this causes memory corruption.&lt;/p&gt;
&lt;p&gt;Also, the thread state is messed up during stack unwinding.
It looks like that &lt;code&gt;gc_safe&lt;/code&gt; should be moved out of the thread struct and made into a proper symbol.
This should ensure correct tracking of thread state during stack unwinding and other thread state changes as the Lisp runtime maintains the dynamic bindings stack.&lt;/p&gt;
&lt;p&gt;I&#39;ve also tackled sockets under Windows.
And they are &lt;em&gt;very&lt;/em&gt; weird.
E.g., one can not simply write, read and poll the socket from different threads.
If the read or poll operation has started earlier than a socket write then the write will just block until the read completes.
This causes SLIME to not work in multithreaded mode since it uses different threads for writing to and reading from a socket.
And I really don&#39;t want to go the async IO path.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Some fixes for Windows threads in SBCL</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-fixes/</link>
			<pubDate>Fri, 09 Jul 2010 00:47:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-fixes/</guid>
			<description>&lt;p&gt;I&#39;ve made several more fixes for the support of Windows threads in SBCL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The code is ported to SBCL 1.40 from 1.36;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The code received some cleanup to ease merging;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Virtual memory page protection attributes are used to implement &amp;ldquo;gc safepoints&amp;rdquo;;
This has brought the performance back to on par with SBCL. Earlier the following code took 1.529 seconds but now it takes 0.089 seconds&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#0086b3&#34;&gt;loop&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;repeat&lt;/span&gt; (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;expt&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;8&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SB-THREAD:INTERRUPT-THREAD&lt;/code&gt; is now supported to be able to interrupt threads;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fixes for various errors in thread synchronization. Not everything has been fixed yet since the tests still sometimes fail with hard-to-reproduce crashes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The source code is now on &lt;a href=&#34;http://github.com/dmitryvk/sbcl-win32-threads&#34;&gt;github&lt;/a&gt;, and the binary is at &lt;a href=&#34;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.40-threads-1.msi&#34;&gt;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.40-threads-1.msi&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>A better replacement for DebugView</title>
			<link>https://dmitryvk.me/posts/2010/debugview-replacement/</link>
			<pubDate>Sun, 04 Jul 2010 21:13:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/debugview-replacement/</guid>
			<description>&lt;p&gt;I&#39;ve been using &lt;a href=&#34;http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx&#34;&gt;DebugView&lt;/a&gt; to debug SBCL code but I&#39;ve kept bumping into its limitations.&lt;/p&gt;
&lt;p&gt;But now I&#39;ve found a replacement for it - it&#39;s the &lt;a href=&#34;http://alter.org.ua/soft/win/dbgdump/&#34;&gt;DbgDump&lt;/a&gt;.
Its main distinction from DebugView is that it&#39;s not a GUI program but rather a CLI program that writes into either file, console, or a network socket (using the syslog protocol).
Therefore when the debuggee generates thousands of log messages per second, I don&#39;t see such a noticeable slowdown.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>More on Windows threads in SBCL</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-windows-threads-continued/</link>
			<pubDate>Wed, 30 Jun 2010 23:35:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-windows-threads-continued/</guid>
			<description>&lt;p&gt;I&#39;ve had to redo interrupt handling in SBCL/Win32, and also rewrite thread suspension and interruption once more.
Having done that, now my tests pass.
With this in mind, thread support is getting closer to completion.
But the volume of changes is getting bigger and bigger which reduces my confidence in swiftly merging this into SBCL HEAD.
But it&#39;s still manageable as a fork.&lt;/p&gt;
&lt;p&gt;I haven&#39;t released the code yet since it requires more polishing and some more testing.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>On inline assembly in SBCL</title>
			<link>https://dmitryvk.me/posts/2010/on-inline-assembly/</link>
			<pubDate>Thu, 24 Jun 2010 23:06:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/on-inline-assembly/</guid>
			<description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;There recently was a discussion on &lt;a href=&#34;http://lisper.ru/&#34;&gt;http://lisper.ru/&lt;/a&gt; about inline assembly in SBCL, and here&#39;s a guide on including inline assembly in SBCL.&lt;/p&gt;
&lt;p&gt;SBCL (as well as in other compilers) contains primitives - language constructs that are not lowerable to other constructs.
SBCL implements these intrinsics both in the IR1 (which represents the code as a control/data flow graph) and in the IR2 (virtual machine).
At the IR1 level, constructs such as &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;lambda&lt;/code&gt; are implemented, while simpler &amp;ldquo;intrinsics&amp;rdquo; (such as arithmetics, memory allocation, etc.) are implemented as virtual machine instructions that have associated code generation procedures.&lt;/p&gt;
&lt;p&gt;These instructions are called VOPs in the SBCL parlance.
SBCL is architected in such a way that the set of VOPs is extensible rather than fixed in stone.
For example, the &lt;code&gt;sb-cga&lt;/code&gt; project (a computer graphics algebra library) implements fast matrix and vector multiplication using the SSE2 instruction set by adding a couple of VOPs.&lt;/p&gt;
&lt;h1 id=&#34;example&#34;&gt;Example&lt;/h1&gt;
&lt;p&gt;Let&#39;s dissect a simple example - let&#39;s add an inline assembly code that XORs two numbers together.&lt;/p&gt;
&lt;p&gt;Abstractly, the assembly for this looks like the following (using the Intel assembly syntax):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;mov&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;result&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;arg1&lt;/span&gt;
&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;xor&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;result&lt;/span&gt;, &lt;span style=&#34;color:#008080&#34;&gt;arg2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;result&lt;/code&gt; is the registry which will contain the result;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arg1&lt;/code&gt; and &lt;code&gt;arg2&lt;/code&gt; are the registers that contain arguments.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In order to invoke this sequence of assembly instructions from Lisp code, we have to do several things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Define a new primitive function (we&#39;ll call it &lt;code&gt;my-xor&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Define a new VOP corresponding to this primitive&lt;/li&gt;
&lt;li&gt;Define a normal function &lt;code&gt;my-xor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;defining-a-new-primitive-function&#34;&gt;Defining a new primitive function&lt;/h2&gt;
&lt;p&gt;By doing the first two operations, SBCL will be able to compile expressions like &lt;code&gt;(my-xor a b)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The macro &lt;code&gt;SB-C:DEFKNOWN&lt;/code&gt; is responsible for defining a primitive. It accepts types of arguments and types of returned value(s).
In this example, we will use only short integers (the &lt;code&gt;FIXNUM&lt;/code&gt; type).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#008080&#34;&gt;sb-c:defknown&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;my-xor&lt;/span&gt; (&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt;) &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;defining-a-new-vop&#34;&gt;Defining a new VOP&lt;/h2&gt;
&lt;p&gt;The macro &lt;code&gt;SB-C:DEFINE-VOP&lt;/code&gt; registers a new VOP. This macro has a lot of parameters related to codegen (such as register selection, argument types, clobbered registers, and lifetimes of arguments), optimization (the &amp;ldquo;cost&amp;rdquo; of an operation), and some others. For this example, the VOP definition looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#008080&#34;&gt;sb-c:define-vop&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;my-xor&lt;/span&gt;)
  (&lt;span style=&#34;color:#990073&#34;&gt;:translate&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;my-xor&lt;/span&gt;)
  (&lt;span style=&#34;color:#990073&#34;&gt;:args&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#990073&#34;&gt;:scs&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;sb-vm::any-reg&lt;/span&gt;))
         (&lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#990073&#34;&gt;:scs&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;sb-vm::any-reg&lt;/span&gt;)))
  (&lt;span style=&#34;color:#990073&#34;&gt;:arg-types&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt;)
  (&lt;span style=&#34;color:#990073&#34;&gt;:results&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#990073&#34;&gt;:scs&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;sb-vm::any-reg&lt;/span&gt;)))
  (&lt;span style=&#34;color:#990073&#34;&gt;:result-types&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt;)
  (&lt;span style=&#34;color:#990073&#34;&gt;:policy&lt;/span&gt; &lt;span style=&#34;color:#990073&#34;&gt;:fast-safe&lt;/span&gt;)
  (&lt;span style=&#34;color:#990073&#34;&gt;:generator&lt;/span&gt;
   &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;
   (&lt;span style=&#34;color:#008080&#34;&gt;sb-c::inst&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;sb-vm::mov&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt;)
   (&lt;span style=&#34;color:#008080&#34;&gt;sb-c::inst&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;sb-vm::xor&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;c&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt;)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&#39;s dissect parts of this definition&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;(sb-c:define-vop (my-xor)&lt;/code&gt; defines the VOP name. In general, the VOP name might be different than the function name. It is often the case that one function has several corresponding VOPs for different argument types (such as multiple variants of &lt;code&gt;+&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;(:translate my-xor)&lt;/code&gt; specifies that the VOP being defined implements the primitive &lt;code&gt;MY-XOR&lt;/code&gt;. This part of the definition specifies that this VOP should be used to translate the &lt;code&gt;(my-xor a b)&lt;/code&gt; expression&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;(:args ...)&lt;/code&gt; and &lt;code&gt;(:results ...)&lt;/code&gt; defines the names of the arguments and result values, and the argument passing ABI.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:scs&lt;/code&gt; specified the set of allowed storage classes. We may consider that a storage class is either a set of registers, the CPU stack, or the FPU stack. The &lt;code&gt;sb-vm::any-reg&lt;/code&gt; storage class corresponds to any of the general-purpose registers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;(:arg-types ..)&lt;/code&gt; и &lt;code&gt;(:result-types ...)&lt;/code&gt; specifies the types of arguments and return values.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;(:policy :fast-safe)&lt;/code&gt; specifies the set of circumstances in which to invoke this VOP (when there is ambiguity). Allowed values are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:small&lt;/code&gt; - when a smaller code size is desired&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:fast&lt;/code&gt; - when faster (but maybe unsafe) code is desired&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:fast-safe&lt;/code&gt; - when it is desired to produce code that is both safe and fast&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;(:generator ...)&lt;/code&gt; defines the meat of the VOP - the code generation procedure.
This procedure may be an arbitrary Lisp code that should invoke some special macros to emit instructions.&lt;/p&gt;
&lt;p&gt;Inside this procedure, we use the &lt;code&gt;SB-C::INST&lt;/code&gt; macro that implements an assembly syntax similar to the Intel assembly language.
Arguments for instructions may be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;numeric constants&lt;/li&gt;
&lt;li&gt;symbolic references to arguments, results, or temporaries&lt;/li&gt;
&lt;li&gt;references to specific registers. For example, &lt;code&gt;SB-VM::EAX-TN&lt;/code&gt; is a reference to &lt;code&gt;EAX&lt;/code&gt; register&lt;/li&gt;
&lt;li&gt;memory address references. For example, the following references a 4-byte word at an address &lt;code&gt;eax + edi * 2 + 3&lt;/code&gt;: &lt;code&gt;(sb-vm::make-ea :dword :base sb-vm::eax-tn :index sb-vm::edi-tn :scale 2 :disp 3)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;references to labels. The labels are created with &lt;code&gt;gen-label&lt;/code&gt; and &lt;code&gt;emit-label&lt;/code&gt;:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;let&lt;/span&gt; ((&lt;span style=&#34;color:#008080&#34;&gt;l&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;gen-label&lt;/span&gt;)) (&lt;span style=&#34;color:#008080&#34;&gt;inst&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;jmp&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;l&lt;/span&gt;) (&lt;span style=&#34;color:#008080&#34;&gt;emit-label&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;l&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;references to various objects. For example, &lt;code&gt;(sb-vm::make-fixup &amp;quot;strlen&amp;quot; :foreign)&lt;/code&gt; is the reference to the external function &lt;code&gt;strlen&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;defining-a-wrapper-function&#34;&gt;Defining a wrapper function&lt;/h3&gt;
&lt;p&gt;So, having defined a VOP, it remains for us to do just a small thing - define a wrapper function &lt;code&gt;MY-XOR&lt;/code&gt; around the primitive &lt;code&gt;MY-XOR&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;my-xor&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt;)
  (&lt;span style=&#34;color:#008080&#34;&gt;my-xor&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This would allow us to not just compile expressions such as &lt;code&gt;(my-xor a b)&lt;/code&gt; but also take a reference to normal Lisp function &lt;code&gt;#&#39;MY-XOR&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At a first glance, this definition of &lt;code&gt;my-xor&lt;/code&gt; is nonsensical: function is defined as a plain recursion without the base non-recursive case.
But there is a catch: the &lt;em&gt;function&lt;/em&gt; &lt;code&gt;MY-XOR&lt;/code&gt; calls the &lt;em&gt;primitive&lt;/em&gt; &lt;code&gt;MY-XOR&lt;/code&gt;. That&#39;s why the compiler generates not a function call but rather generates the code for the VOP corresponding to the primitive &lt;code&gt;MY-XOR&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&#39;s make sure that this understanding of this code is correct:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(disassemble &#39;my-xor)
=&amp;gt;
; disassembly for MY-XOR
; 02DED843:       488BD1           MOV RDX, RCX               ; no-arg-parsing entry point
;       46:       4831FA           XOR RDX, RDI               ; &amp;lt;-- beginning of our code
;       49:       488BE5           MOV RSP, RBP
;       4C:       F8               CLC
;       4D:       5D               POP RBP
;       4E:       C3               RET
;       4F:       CC0A             BREAK 10                   ; error trap
;       51:       02               BYTE #X02
;       52:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       53:       54               BYTE #X54                  ; RCX
;       54:       CC0A             BREAK 10                   ; error trap
;       56:       02               BYTE #X02
;       57:       08               BYTE #X08                  ; OBJECT-NOT-FIXNUM-ERROR
;       58:       95               BYTE #X95                  ; RDX
;       59:       CC0A             BREAK 10                   ; error trap
;       5B:       04               BYTE #X04
;       5C:       08               BYTE #X08                  ; OBJECT-NOT-FIXNUM-ERROR
;       5D:       FED501           BYTE #XFE, #XD5, #X01      ; RDI
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This listing has 2 instructions starting at offset 0x02DED843 that are exactly the output of just defined VOP. And the rest is the standard prolog and epilogue, and the code to check arguments&amp;rsquo; types.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Let&#39;s also try to use the newly defined primitive inside a normal function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;foo&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt;)
  (&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;declare&lt;/span&gt; (&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;fixnum&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt;)
           (&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;optimize&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;speed&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;3&lt;/span&gt;) (&lt;span style=&#34;color:#008080&#34;&gt;safety&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;)))
  (&lt;span style=&#34;color:#008080&#34;&gt;my-xor&lt;/span&gt; (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;1+&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;a&lt;/span&gt;) (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;1+&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;b&lt;/span&gt;)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And let&#39;s have a look at its disassembly:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;; disassembly for FOO
; 0325A727:       48FFC2           INC RDX                    ; no-arg-parsing entry point
;       2A:       48FFC7           INC RDI
;       2D:       48C1E203         SHL RDX, 3
;       31:       48C1E703         SHL RDI, 3
;       35:       488BD2           MOV RDX, RDX               ; &amp;lt;-- the code generated for MY-XOR
;       38:       4831FA           XOR RDX, RDI               ; &amp;lt;--
;       3B:       488BE5           MOV RSP, RBP
;       3E:       F8               CLC
;       3F:       5D               POP RBP
;       40:       C3               RET
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this listing, we can see that the SBCL generated exactly the code that we wanted.&lt;/p&gt;
&lt;p&gt;The code to generate such a simple inline assembly got quite verbose.
This is because we utilize the full capabilities of the compiler, not just a simpler inline assembly.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>ICFPC has finished</title>
			<link>https://dmitryvk.me/posts/2010/icfpc-finished/</link>
			<pubDate>Tue, 22 Jun 2010 23:13:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/icfpc-finished/</guid>
			<description>&lt;p&gt;Well, the ICFPC is now finished in which I, technically, participated. &amp;ldquo;Technically&amp;rdquo; is because I skipped the beginning of its and half of the second day. And on the third day I tried to get some rest, and for the last half a day I was at work. So, it wasn&#39;t productive during this year&#39;s contest. I&#39;m hoping for the next year.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>More fixes for SBCL Windows threads</title>
			<link>https://dmitryvk.me/posts/2010/more-sbcl-win32-threads-fixes/</link>
			<pubDate>Sun, 06 Jun 2010 01:28:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/more-sbcl-win32-threads-fixes/</guid>
			<description>&lt;p&gt;With a tip from Anton Vodonosov I&#39;ve found and fixed two more threading-related bugs that lead to handle and memory leak.&lt;/p&gt;
&lt;p&gt;The new version of SBCL is available at &lt;a href=&#34;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.36.16-threads-3.msi&#34;&gt;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.36.16-threads-3.msi&lt;/a&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Fixes for FFI callbacks in SBCL</title>
			<link>https://dmitryvk.me/posts/2010/callback-fixes/</link>
			<pubDate>Wed, 02 Jun 2010 23:53:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/callback-fixes/</guid>
			<description>&lt;p&gt;After adding threads into the Windows port of SBCL there were some errors in the way Lisp callbacks worked when called from the C code: when running Lisp code in a callback the thread had its &lt;code&gt;gc_safe&lt;/code&gt; flag set. This flag means that this thread is in a section of code that is safe regarding the garbage collector and that it promises not to touch the Lisp heap. But this invariant is clearly violated - so callbacks should clear this flag and check whether the thread should suspend to ensure safe garbage collection. And similarly, when returning to the C code we should set this flag and check the thread suspension predicate.&lt;/p&gt;
&lt;p&gt;The fixes are in github and the fixed binary is at &lt;a href=&#34;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.36.16-threads-2.msi&#34;&gt;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.36.16-threads-2.msi&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The next thing on my list is to fix the &lt;code&gt;read-char-no-hang&lt;/code&gt; function for Windows sockets.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Pre-alpha version of SBCL with Windows threads</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-with-threads-pre-alpha/</link>
			<pubDate>Sun, 30 May 2010 22:34:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-with-threads-pre-alpha/</guid>
			<description>&lt;p&gt;I&#39;ve uploaded the first version of SBCL with support for Windows threads to &lt;a href=&#34;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.36.16-threads.msi&#34;&gt;http://sites.google.com/site/dmitryvksite/sbcl-distr/sbcl-1.0.36.16-threads.msi&lt;/a&gt;. So I would like to ask fellow lispniks who are reading this and are using Windows to test this and report any bugs. In particular, I&#39;m interested in whether it works under different versions of Windows (XP, Vista, 7, 2003, 2008) and with different CPUs (x86 and x86-64).&lt;/p&gt;
&lt;p&gt;In the released version, threads and threading primitives should basically work with the exception of the &lt;code&gt;sb-thread:interrupt-thread&lt;/code&gt; and &lt;code&gt;sb-thread:terminate-thread&lt;/code&gt; functions. Note that the performance of this version may be significantly worse than the unithreaded version since a lot of things are made in a quick-and-dirty manner without any regard for performance. As an example, a simple loop such as &lt;code&gt;(loop repeat (expt 10 8))&lt;/code&gt; runs about 10 times longer.&lt;/p&gt;
&lt;p&gt;SLIME is working although it sometimes behaves weirdly.&lt;/p&gt;
&lt;p&gt;I&#39;ve tried to run the &lt;code&gt;hunchentoot&lt;/code&gt; web server as a test and it didn&#39;t work. It happens due to the lack of non-blocking read in &lt;code&gt;usocket&lt;/code&gt; library, which is predicated on the lack of support for non-blocking socket read and polling in the Windows port of SBCL.&lt;/p&gt;
&lt;p&gt;Thanks in advance to whoever will test and report the results!&lt;/p&gt;
&lt;p&gt;PS. A couple of words on how to report bugs in a way that would most help debug them. There is a small &lt;a href=&#34;http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx&#34;&gt;DebugView&lt;/a&gt; utility that shows the debug output coming from the OutputDebugString function. If you attach this output to your bug report it would help enormously.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Safepoints for thread suspension</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-safepoints/</link>
			<pubDate>Thu, 27 May 2010 00:25:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-safepoints/</guid>
			<description>&lt;p&gt;It was significantly easier to implement thread suspension on Windows using the safepoints rather than using asynchronous signal processing. The lack of them on Windows (which is a controversial topic when comparing Windows APIs to Unix APIs) made it significantly harder. The implementation of safepoints for SBCL was independently done by Paul Khuong (&lt;a href=&#34;http://repo.or.cz/w/sbcl/pkhuong.git/shortlog/refs/heads/gc-safe-points&#34;&gt;http://repo.or.cz/w/sbcl/pkhuong.git/shortlog/refs/heads/gc-safe-points&lt;/a&gt;) which I gladly took as a basis. The GC-polling code in the safepoints is not yet optimal, though.&lt;/p&gt;
&lt;p&gt;For now, the garbage collector does not correctly support having code regions that don&#39;t participate in the garbage collection process - that is, code that blocks or calls the foreign code.&lt;/p&gt;
&lt;p&gt;And, of course, the optimizations are to be done.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>A better terminal emulator for Cygwin</title>
			<link>https://dmitryvk.me/posts/2010/cygwin-mitty/</link>
			<pubDate>Sun, 23 May 2010 10:23:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/cygwin-mitty/</guid>
			<description>&lt;p&gt;I&#39;ve discovered the &lt;a href=&#34;http://code.google.com/p/mintty/&#34;&gt;mintty&lt;/a&gt; &amp;ndash; a great terminal emulator for Cygwin.&lt;/p&gt;
&lt;p&gt;Compared to the built-in Windows terminal, Mintty is like day and night. Its UI is resizable, I can set any font, I can select, copy and paste text, and it is fast.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>More troubles in Windows thread suspension</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-roadblock/</link>
			<pubDate>Thu, 20 May 2010 00:06:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-roadblock/</guid>
			<description>&lt;p&gt;For now, my work on threading support in SBCL is stalled since I still can not implement thread suspension for garbage collection.
The main problem is that Windows API does not offer asynchronous signals (which are available on all other platforms and are surfaced as a &lt;code&gt;pthread_kill&lt;/code&gt; function in POSIX Threads API).&lt;/p&gt;
&lt;p&gt;I&#39;ve tried several options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The thread in pseudo-atomic sections suspends on its own, and in all the rest cases uses the &lt;code&gt;SuspendThread&lt;/code&gt;. But it&#39;s fraught with problems in many places: threads sometimes just hung, there were errors inside the garbage collector and I was getting spurious page faults. I later understood that this was due to stopping the threads in the wrong place; SBCL uses not just pseudo-atomic sections for non-interruptible code, but also the thread signal mask.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then I tried adding a signal mask to a thread and considered this mask when suspending the thread: first, we suspend the thread using &lt;code&gt;SuspendThread&lt;/code&gt;, and if the thread has masked the &lt;code&gt;SIG_STOP_FOR_GC&lt;/code&gt; signal, the thread is resumed using &lt;code&gt;ResumeThread&lt;/code&gt; and we sleep for a while and then repeat. Having done this, threads have stopped hanging, but now I got different behavior: as soon as garbage collection completes and the threads resume, some threads discover invalid virtual memory protection flags. I attribute this to the thread suspending inside the exception handler and so it observes the exception handler context instead the proper thread context.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With all of that, I conclude that I won&#39;t be able to achieve asynchronous non-cooperative thread suspension.&lt;/p&gt;
&lt;p&gt;One of the things that I&#39;ve researched was the way the .NET garbage collector handles thread suspension (&lt;a href=&#34;http://msdn.microsoft.com/en-us/library/678ysw69.aspx)&#34;&gt;http://msdn.microsoft.com/en-us/library/678ysw69.aspx)&lt;/a&gt;. .NET CLR tracks suspension requests for each thread. And compiler inserts special instructions - gc safepoints - so that the thread would check from time to time whether it should suspend. Specific CPU instructions used for the safepoints are not as important. These instructions could be, for example, a read from the special region of memory which is unmapped when garbage collection is started, causing page fault and exception in the reading thread and giving it a chance to react to garbage collection. When the thread leaves the bounds of CLR-managed code (that is, performs a blocking operation or calls out to foreign code), it sets the flag that signals that this thread will not touch the GC heap. And when the thread returns back into CLR-managed code, it checks whether it should stop and wait for GC to complete. And there is a weird quirk - if a thread did not stop within 250 milliseconds it will be forcefully stopped using &lt;code&gt;SuspendThread&lt;/code&gt;. A thread might not stop timely if did not reach the safepoint within a long time. In the case of .NET, this might happen if the thread is running a long loop that does not call other methods or perform memory allocations. In this regard, the .NET garbage collector is much less careful than the JVM which inserts safepoints not just to method calls but also to backward jumps (any loop is implemented as a backward jump) which guarantees that thread will eventually reach a safepoint.&lt;/p&gt;
&lt;p&gt;I shall try to employ a similar technique.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Safepoints will be placed in several kinds of places:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;exit from &lt;code&gt;pseudo-atomic&lt;/code&gt; section&lt;/li&gt;
&lt;li&gt;change of thread signal mask&lt;/li&gt;
&lt;li&gt;handler for trap CPU instructions&lt;/li&gt;
&lt;li&gt;return from foreign code&lt;/li&gt;
&lt;li&gt;return from blocking operations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When entering a foreign code (such as a C function call) or invoking blocking operations, a thread will set a flag to signify that it will not do anything with the GC-managed heap, so this thread may be ignored for the purpose of suspending all mutator threads during GC cycle&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As I don&#39;t want to go too deep into the compiler, I will try to implement GC as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, all threads are suspended&lt;/li&gt;
&lt;li&gt;GC enumerates all threads and checks their state:
&lt;ul&gt;
&lt;li&gt;if the thread is already safe for garbage collection, it is resumed&lt;/li&gt;
&lt;li&gt;if the thread is in a pseudo-atomic section or has masked &lt;code&gt;SIG_STOP_FOR_GC&lt;/code&gt;, then it is resumed and GC awaits while the thread leaves this section&lt;/li&gt;
&lt;li&gt;If the thread is running a Lisp code, put a breakpoint on the closest &lt;code&gt;jmp&lt;/code&gt; or &lt;code&gt;call&lt;/code&gt; instruction by replacing it with a trap instruction and resume the thread. Soon enough the thread will reach the breakpoint and enter the exception handler. The exception handle will restore the proper instruction and suspend the thread.&lt;/li&gt;
&lt;li&gt;So far I haven&#39;t come up with what to do if the thread runs neither a Lisp code nor a foreign code, is not in a pseudo-atomic section and its signals are unmasked. We could probably resume the thread, wait for a little and then try again.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
		</item>
		<item>
			<title>More progress in Windows threading for SBCL</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-working/</link>
			<pubDate>Sun, 02 May 2010 11:59:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-working/</guid>
			<description>&lt;p&gt;There is some progress on Windows threads for SBCL.&lt;/p&gt;
&lt;p&gt;I am using the code shown below as a test. As of now, it does run without hanging. That is, concurrent memory allocation in multiple threads with concurrent garbage collection requests is now working. I will check it more thoroughly on a beefier 4-core computer for multiple hours to ensure that the approach is right, but for now it seems to be working fine.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;cons-lot&lt;/span&gt; (&lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;stream&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;char&lt;/span&gt;)
  (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;sleep&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;2&lt;/span&gt;)
  (&lt;span style=&#34;color:#0086b3&#34;&gt;loop&lt;/span&gt;
    (&lt;span style=&#34;color:#0086b3&#34;&gt;loop&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;repeat&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;10&lt;/span&gt;
      &lt;span style=&#34;color:#008080&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;ar&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;make-array&lt;/span&gt; (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;1024&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;1024&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;1/2&lt;/span&gt;) &lt;span style=&#34;color:#990073&#34;&gt;:initial-element&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;0&lt;/span&gt;)
      &lt;span style=&#34;color:#0086b3&#34;&gt;do&lt;/span&gt; (&lt;span style=&#34;color:#0086b3&#34;&gt;setf&lt;/span&gt; (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;aref&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;ar&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;1000&lt;/span&gt;) &lt;span style=&#34;color:#099&#34;&gt;112&lt;/span&gt;))
    (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;stream&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;&amp;#34;~A&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;char&lt;/span&gt;)
    (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;finish-output&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;stream&lt;/span&gt;)))

(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;threaded-cons-lot&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;n&lt;/span&gt;)
  (&lt;span style=&#34;color:#0086b3&#34;&gt;loop&lt;/span&gt;
    &lt;span style=&#34;color:#008080&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;stream&lt;/span&gt; &lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;*standard-output*&lt;/span&gt;
    &lt;span style=&#34;color:#008080&#34;&gt;repeat&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;n&lt;/span&gt;
    &lt;span style=&#34;color:#0086b3&#34;&gt;do&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;sb-thread:make-thread&lt;/span&gt; (&lt;span style=&#34;color:#0086b3&#34;&gt;lambda&lt;/span&gt; () (&lt;span style=&#34;color:#008080&#34;&gt;cons-lot&lt;/span&gt; &lt;span style=&#34;color:#458;font-weight:bold&#34;&gt;stream&lt;/span&gt; &lt;span style=&#34;color:#d14&#34;&gt;#\.&lt;/span&gt;)))))

(&lt;span style=&#34;color:#008080&#34;&gt;threaded-cons-lot&lt;/span&gt; &lt;span style=&#34;color:#099&#34;&gt;4&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After all, lack of asynchronous IPC in Windows API is noticeable. Correct thread suspension is achievable in POSIX (it takes to carefully manipulate signal mask to ensure that the signal does not arrive at unfortunate moments), while it becomes very fragile on Windows. There are not a lot of options for asynchronous thread communication: basically, we can use &lt;code&gt;SuspendThread&lt;/code&gt; and analyze and manipulate the thread state (which is very non-trivial). Another option is to implement cooperative thread suspension in which the thread itself should on its own periodically check whether it should suspend or interrupt. I don&#39;t claim to be an expert in this area, but it seems to be a significant drawback of Windows APIs in the IPC area.&lt;/p&gt;
&lt;p&gt;(On the other note, thread synchronization in Windows is quite tricky and fragile due to internals of asynchronous inter-thread communication. For example, asynchronous procedure call may cause a thread waiting on a synchronization event to miss a notification from &lt;code&gt;PulseAll&lt;/code&gt; function.)&lt;/p&gt;
&lt;p&gt;In SBCL, garbage collection is implemented in the following manner:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The thread discovers that it is time to do a garbage collection cycle. The thread may discover this either while performing an allocation (in which case the thread is inside a pseudo-atomic section with signals masked) or due to explicit call to &lt;code&gt;SB-EXT:GC&lt;/code&gt; (in which case the thread is not in the pseudo-atomic case).&lt;/li&gt;
&lt;li&gt;The thread locks the &lt;code&gt;*ALREADY-IN-GC*&lt;/code&gt; mutex whils having its signals unmasked. This is required in order for multiple threads to be able to invoke the garbage collection: one thread will take the lock and other threads will be stoppable (since the signals are unmasked).&lt;/li&gt;
&lt;li&gt;The thread that has locked the mutex sends the &lt;code&gt;SIG_STOP_FOR_GC&lt;/code&gt; signal to all other threads and awaits for them to actually stop. When the thread stops, it set its &lt;code&gt;thread.state&lt;/code&gt; field to &lt;code&gt;STATE_SUSPENDED&lt;/code&gt; and signals the thread&#39;s &lt;code&gt;state_cond&lt;/code&gt; condition variable.&lt;/li&gt;
&lt;li&gt;The threads receive the signals and suspend themselves. The key point is that the thread will receive the signal only when it is ready to handle it. For example, the thread is able to handle the signal and suspend while it is blocked trying to lock the &lt;code&gt;*ALREADY-IN-GC*&lt;/code&gt; mutex.&lt;/li&gt;
&lt;li&gt;When all threads are suspended, a garbage collection is performed. While one thread performs the garbage collection, all threads are waiting on the &lt;code&gt;state_cond&lt;/code&gt; conditional variables.&lt;/li&gt;
&lt;li&gt;Threads have their state set to &lt;code&gt;STATE_RUNNING&lt;/code&gt; and are resumed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In Win32 API there are significant challenges with the 4th item. There is no way to have the thread code execute some code in such a way that would be safe for the thread without having the thread be in some special state. If we ignore safety then there is the &lt;code&gt;SetThreadContext&lt;/code&gt; function that lets us redirect the thread to arbitrary code. If we limit the thread only to some special state, then there is the &lt;code&gt;QueueUserAPC&lt;/code&gt; function, but APCs (async procedure calls) are invoked only while the thread is in some special state - that is, while it&#39;s blocked on &lt;code&gt;SleepEx&lt;/code&gt;, &lt;code&gt;WaitForSingleObjectEx&lt;/code&gt; or &lt;code&gt;WaitForMultipleObjectsEx&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As an alternative, there a different technique to achieve thread notification which is used in the JVM. A special code sequence is inserted in some locations of a program that somehow checks whether the thread should suspend or interrupt or do something special. This request can be communicated via the memory protection attributes of a special memory page so that accessing it is normally a no-op but in special circumstances it would redirect the thread to the signal handler. This is a viable approach but it requires more work and requires the thread to periodically do something.&lt;/p&gt;
&lt;p&gt;So my plan is as follows. Since I can&#39;t make the thread stop in safe way, then I will have to resort to more complicated way of stopping threads using &lt;code&gt;SuspendThread&lt;/code&gt;. For garbage collection, there are two hazards - if another thread locks something that is needed for a garbage collector, and if the garbage collector witnesses an object in the middle of its initilization. That&#39;s why all the locks used by the garbage collector must be taken right at the start of garbage collection cycle. An incomplete object initialization corresponds to a pseudo-atomic section; therefore we can set the thread&#39;s &lt;code&gt;pseudo-atomic-interrupted&lt;/code&gt; flag so that the thread would know that it should stop as it leaves the pseudo-atomic section. If a thread is inside a pseudo-atomic and tries to invoke the garbage collection then it must grab the GC mutex - therefore we use &lt;code&gt;ptread_mutex_trylock&lt;/code&gt; instead of &lt;code&gt;pthread_mutex_lock&lt;/code&gt; so that one thread would successfully grab the mutex and the other threads would know to stop. And the thread a normal state is stopped with the &lt;code&gt;SuspendThread&lt;/code&gt; with all of its locks kept held which means that the garbage collector must not take the same locks to avoid deadlocking. And the starting and stopping of the GC is done with a pair of &lt;code&gt;AutoResetEvent&lt;/code&gt;s: &lt;code&gt;gc_suspend_event&lt;/code&gt; and &lt;code&gt;gc_resume_event&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now I need to verify the proper functioning of the thread stopping and come up with a way to interrupt running threads which is, for example, used by SLIME to interrupt long-running processes.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Progress in Windows threading support in SBCL</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-progress/</link>
			<pubDate>Fri, 09 Apr 2010 01:15:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-progress/</guid>
			<description>&lt;p&gt;I&#39;ve moved a little bit forward with Windows thread support in SBCL. Now I can the thread to start, and even the garbage collection may run when multiple threads are running. That&#39;s not entirely true since stopping of threads is not fully implemented. For example, &lt;code&gt;gc_stop_the_world&lt;/code&gt; would if fail if the thread was in a pseudo-atomic section but it should be easy to fix. At least I got simple examples to work.&lt;/p&gt;
&lt;p&gt;But now I got to the point that I&#39;m not so sure whether it&#39;s right to stop the thread by pushing a new frame into its call stack. While the thread is being hijacked by a new call stack frame, it might be holding some important system resources (that are not designed with such a case in mind) that might be necessary for the garbage collector to run.&lt;/p&gt;
&lt;p&gt;If this is the case then I would have to come up with other ways of stopping the threads. For example, it&#39;s possible to avoid stopping the thread if the Lisp-side of its stack and the Lisp heap will be untouched by that thread. But I&#39;ll leave that option for a later time in case the simpler ways of stopping will not work somehow.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Windows threads progress for SBCL</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-progress-2/</link>
			<pubDate>Mon, 29 Mar 2010 00:31:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-progress-2/</guid>
			<description>&lt;p&gt;I am continuing to hack on SBCL to have working thread support for Windows.&lt;/p&gt;
&lt;p&gt;The Thread-Local Storage area is stored in the Arbitrary Data Slot of TIB (Thread Information Block) which is mapped in every thread to the address &lt;code&gt;FS:0x14&lt;/code&gt;. Some of the VOPs now take more instructions and use more registers and do more memory accesses since in other ports SBCL can directly address the TLS area, but instead, in Windows, we have to load the pointer to the TLS area into a register. So far is too hard to quantify the performance effects of this.&lt;/p&gt;
&lt;p&gt;I&#39;m still kind of slow at this low-level stuff. I&#39;ve spent a week debugging an issue caused by my inattentiveness. Incidentally, this made me get to know the GDB better. GDB is a brilliant debugger. This might be hard to see behind its lowly command-line UI. One of the nice things is that GDB has macros that help implement application-specific debugging functionality. Before that, I mostly used the Visual Studio debugger and didn&#39;t expect the GDB to be so good.&lt;/p&gt;
&lt;p&gt;As for SBCL, today I had a first working build that would run (earlier it wouldn&#39;t get past the cold init). TLS is apparently also working.&lt;/p&gt;
&lt;p&gt;Now I need to work on the runtime to teach it to create threads and suspend them for garbage collection purposes.&lt;/p&gt;
&lt;p&gt;For the thread suspension, I&#39;m planning to inject a stack frame for a fake call to the function that will await the resumption signal (as in &lt;a href=&#34;http://github.com/dmitryvk/testw32/blob/master/plant_stack.c)&#34;&gt;http://github.com/dmitryvk/testw32/blob/master/plant_stack.c)&lt;/a&gt;. This should allow for correctly suspending the threads that are performing blocking syscalls as well as threads that running userspace code.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>How to access thread-local data in Windows</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-no-gs/</link>
			<pubDate>Thu, 18 Mar 2010 00:21:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-no-gs/</guid>
			<description>&lt;p&gt;I have stopped liking the idea to utilize the GS segment register for storing the pointer to a thread-local storage. Despite my efforts, the GS register still sometimes ends up containing zero.&lt;/p&gt;
&lt;p&gt;Apart for the GS registers there are different options for accessing the thread-local data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The ES register. Clozure CL compiler for Windows uses this register to access thread-local storage and it also avoids emitting &amp;ldquo;string&amp;rdquo; instructions (such as &lt;code&gt;CMPS&lt;/code&gt;) since those instructions use the ES register. Apparently, they are not used since in Clozure CL only EAX register may contains an untagged value which also helps to make the garbage collection precise. Consequently, this approach would require SBCL to not generate string instructions and to save/restore the ES register while calling foreign code. I consider such tradeoffs  unacceptable.&lt;/li&gt;
&lt;li&gt;Inside the Thread Information Block in the Arbitrary Data Field. This field is always available for any thread at the adress &lt;code&gt;%FS:0x14&lt;/code&gt;. Using this approach will entail changing in just some places related to handling the current thread. Having skimmed the code, it seems that there are just a couple of such places and they are pretty straightforward.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For now I&#39;m betting on using &lt;code&gt;%FS:0x14&lt;/code&gt;.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Microsoft&#39;s documentation style</title>
			<link>https://dmitryvk.me/posts/2010/microsoft-docs-style/</link>
			<pubDate>Mon, 08 Mar 2010 08:53:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/microsoft-docs-style/</guid>
			<description>&lt;p&gt;MSDN is in general a nice documention collection but sometimes reading it makes me sad.&lt;/p&gt;
&lt;p&gt;Today&#39;s exhibit the &lt;code&gt;SignalObjectAndWait&lt;/code&gt; function. It contains the following note:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note that the &amp;ldquo;signal&amp;rdquo; and &amp;ldquo;wait&amp;rdquo; are not guaranteed to be performed as an atomic operation. Threads executing on other processors can observe the signaled state of the first object before the thread calling SignalObjectAndWait begins its wait on the second object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Everywhere (except the MSDN) it is written that the &lt;code&gt;SignalObjectAndWait&lt;/code&gt; performs the signal and wait operations &lt;strong&gt;atomically&lt;/strong&gt; (even the Jeffrey Richter&#39;s book agrees) whilst MSDN states the opposite - that it&#39;s &lt;strong&gt;not atomic&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I&#39;m really confused about this and don&#39;t know whether I should rely on this function anymore. This a pretty fundamental synchronization primitive and it would be bad to avoid using it.&lt;/p&gt;
&lt;p&gt;And the funny thing is that the older version of the documention also states that it&#39;s an atomic operation.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Windows APC won&#39;t be of use to me</title>
			<link>https://dmitryvk.me/posts/2010/windows-apc-no-go/</link>
			<pubDate>Sun, 07 Mar 2010 02:46:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/windows-apc-no-go/</guid>
			<description>&lt;p&gt;I was happy to see that Windows has support for Asynchronous Procedure Calls (APCs). APC seems to have the same functionality that the signals have, i.e. the Windows API allows to run some code in the context of another thread. But there&#39;s a catch - APCs are only invoked during specific moments.&lt;/p&gt;
&lt;p&gt;Hence I had to resort to calling code in the context of another thread by manipulating the stack and the context of a thread in order to &amp;ldquo;plant&amp;rdquo; a call to the function. At least, that&#39;s what I&#39;ve been able to conjure as a hack. I still have to find out how blocking calls would work in the interrupted thread but simple tests show that evertything should be OK with it.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>How to use the GS register in Windows</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-win32-threads-gs-selector/</link>
			<pubDate>Sat, 06 Mar 2010 06:32:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-win32-threads-gs-selector/</guid>
			<description>&lt;p&gt;Thanks to a hint, I&#39;ve been able to understand how to use the &lt;code&gt;%GS&lt;/code&gt; register. So the plan to access the TLS is as follows: when a thread starts it saves the pointer to its state (more specifically, a segment selector for a new segment whose base is a pointer to a structure with thread-specific data and with no limit) at the address &lt;code&gt;%FS:0x14&lt;/code&gt; (which corresponds to the Arbitrary Data Slot of the &lt;a href=&#34;http://en.wikipedia.org/wiki/Win32_Thread_Information_Block&#34;&gt;Windows Thread Information Block&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;And at certain moments, that selector is copied into the &lt;code&gt;%GS&lt;/code&gt; register:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when a thread starts&lt;/li&gt;
&lt;li&gt;after each call to a foreign function&lt;/li&gt;
&lt;li&gt;when entering the &amp;ldquo;planted&amp;rdquo; function for hijacking a thread&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At first, I thought that the &lt;code&gt;%GS&lt;/code&gt; is being reset every time the scheduler preempts the thread. But experiments have shown that &lt;code&gt;%GS&lt;/code&gt; is only being reset when calling Windows API functions. I was confused by the fact that I was unable to set this register via the &lt;code&gt;SetThreadContext&lt;/code&gt; at all &amp;ndash; that&#39;s why I thought that this register is not persisted in the thread context.&lt;/p&gt;
&lt;p&gt;Implementing this approach would require changing the way foreign functions are called and to take it into account when implementing thread hijacking via stack frame planting.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>How to adapt SBCL&#39;s garbage collection and threading to Windows</title>
			<link>https://dmitryvk.me/posts/2010/sbcl-internals-abi/</link>
			<pubDate>Sun, 28 Feb 2010 21:00:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/sbcl-internals-abi/</guid>
			<description>&lt;p&gt;I&#39;m trying to implement threading support in the Windows version of SBCL. I&#39;ve been looking at the source code and I was quite surprised that this had not been implemented yet. I guess the SBCL community is quite small.&lt;/p&gt;
&lt;p&gt;I did a preliminary analysis of what needs to be done to support threads and how it can be done.&lt;/p&gt;
&lt;p&gt;The SBCL sources are quite interesting. There are a lot of places which hadn&#39;t seen attention for quite a long time. And several places in the source code are quite involved to hard to wrap my head around &amp;ndash; especially code that deals with signals and signals masking. The documentation is quite scarce (especially when it comes to introductory materials) but on the whole, it&#39;s approachable. The old CMUCL papers and articles are quite useful (since SBCL is based on CMUCL) and are linked from the &lt;a href=&#34;http://sbcl-internals.cliki.net/Papers&#34;&gt;sbcl-internals&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;SBCL uses the OS API in nontypical ways. I was particularly paying attention to things that are required to make SBCL work on Windows.&lt;/p&gt;
&lt;p&gt;The primary feature of Lisp that made SBCL developers go to great lengths and employ various tricks and hacks is, of course, the garbage collector. SBCL performs garbage collection if either successive allocation fails or periodically (the trigger is based on the number of bytes since the last collection). The garbage collection is performed in the calling thread and it suspends all other threads. When all threads are suspended, it starts to scan the garbage collection roots (that is, stacks of all threads and global variables). Having completed the garbage collection, all stopped threads are resumed.&lt;/p&gt;
&lt;p&gt;As memory allocation is a frequently invoked operation in Lisp, it should run as fast as possible. For this, every thread in SBCL has a per-thread memory region in which allocation happens without locking by just a simple bump allocator.&lt;/p&gt;
&lt;p&gt;But memory allocation is not an atomic operation and consists of several steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increase the pointer to free memory by the allocation size&lt;/li&gt;
&lt;li&gt;Compare the pointer with the bounds of the free region&lt;/li&gt;
&lt;li&gt;Initialize the object in the allocated space.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, suppose the garbage collector stopped the thread in the middle of the allocation. It would observe an inconsistent state in which the GC invariants are violated and would corrupt the memory if it would try to do collection in such a case.&lt;/p&gt;
&lt;p&gt;That&#39;s why SBCL employs a technique named &amp;ldquo;pseudo-atomic sections&amp;rdquo;. These sections are short segments of code that are handled specially by the garbage collector - the garbage collector ensures that no thread is suspended inside a pseudo-atomic section.&lt;/p&gt;
&lt;p&gt;The pseudo-atomic sections are implemented as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Upon entering the pseudo-atomic section the thread sets the flag to signify that it&#39;s in such a section&lt;/li&gt;
&lt;li&gt;The garbage collector checks this flag for each thread and if it&#39;s set, sets another flag to signify that the garbage collector is waiting for this thread and unblocks this thread&lt;/li&gt;
&lt;li&gt;Upon exiting the pseudo-atomic section, the thread checks for this flag and suspends itself if necessary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While starting the collection, the garbage collector ensures that the collection is not running already and if this is the case, it waits for the collection to complete and then retries the memory allocation.&lt;/p&gt;
&lt;p&gt;When running under Linux, the SBCL uses signals delivered to specific threads in order to stop or resume their execution. It uses real-time signals for that purpose since normal signals are not queued: the thread will skip a signal if already has a signal queued for it while that signal is masked. For correct signal handling, threads manipulate their signals mask.&lt;/p&gt;
&lt;p&gt;On Windows, it makes no sense to use signals since Windows does not have signals (not even talking about real-time signals). But it supports suspending threads. After the thread is suspended, it is possible to query or set the thread context. This lets us, for example, imitate a function call. This lets us implement thread interruption by invoking a special code inside it. Also, this is one of the ways to synchronize pseudo-atomic sections with the garbage collector.&lt;/p&gt;
&lt;p&gt;Every thread has an area that is local to the current thread. On Linux, the pointer to it is stored in either the &lt;code&gt;%FS&lt;/code&gt; register on x86 or the &lt;code&gt;%R12&lt;/code&gt; register on x86-64. Windows lets each thread store an arbitrary pointer-sized value at the address &lt;code&gt;%FS:0x14&lt;/code&gt;. And some runtimes use the &lt;code&gt;%GS&lt;/code&gt; register to store the base pointer to the thread-local data area. Using the functions &lt;code&gt;NtQueryInformationProcess/NtSetInformationProcess&lt;/code&gt; we can set the base and limit for the memory segment, and then using the &lt;code&gt;GetThreadContext/SetThreadContext&lt;/code&gt; it is possible to set the selector for this segment in a segment register (&lt;code&gt;%GS&lt;/code&gt; for Windows x86 since &lt;code&gt;%FS&lt;/code&gt; is already taken for Thread Execution Block). A segment register stored the segment selector which is defined in the LDT (Local Descriptor Table). It is only possible to have 8192 segment selectors which limits the possible number of threads to just 8192.&lt;/p&gt;
&lt;p&gt;In a per-thread area we would be able to store the following data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dynamic binding stack&lt;/li&gt;
&lt;li&gt;control stack&lt;/li&gt;
&lt;li&gt;thread flags&lt;/li&gt;
&lt;li&gt;thread synchronization objects&lt;/li&gt;
&lt;li&gt;current dynamic values of symbols&lt;/li&gt;
&lt;li&gt;per-thread allocation area&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&#39;s see how the GENCGC garbage collector allocates memory. Memory is allocated from the per-thread memory region in a pseudo-atomic code section. The allocation sequence is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The thread enters a pseudo-atomic section&lt;/li&gt;
&lt;li&gt;If the per-thread region has sufficient free space to satisfy the allocation request, the allocation happens from this region&lt;/li&gt;
&lt;li&gt;Otherwise, a new region is allocated (this might trigger garbage collection)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, about the dynamic bindings for special variables. SBCL stores in the symbol structure the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;global value&lt;/li&gt;
&lt;li&gt;TLS index for the per-thread current value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, there is a per-thread binding stack that stores the pairs consisting of a symbol and the symbol&#39;s value. When a code dynamically binds a special variable to a new value, it pushes the symbol and its old value to the bindings stack and writes a new value into a thread-local area using the TLS index. Upon leaving the scope of dynamic binding, everything is done in reverse order.&lt;/p&gt;
&lt;p&gt;The Lisp stack (also named the control stack) is separated from the foreign code stack (named the numeric stack) and from the dynamic bindings stack. The difference between the Lisp stack and the foreign code stack is that the Lisp stack only contains pointers to boxed Lisp objects and is scanned by the garbage collector while the foreign code stack is not inspected by the garbage collector at all.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;SB-THREAD&lt;/code&gt; package defines a set function to control threads:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make-thread&lt;/code&gt; creates a new thread&lt;/li&gt;
&lt;li&gt;&lt;code&gt;join-threads&lt;/code&gt; waits for thread completion&lt;/li&gt;
&lt;li&gt;&lt;code&gt;interrupt-thread&lt;/code&gt; interrupts a thread. Interruption is analogous to UNIX signals: thread stops doing whatever it was doing and invokes the specified function. If the thread is already being interrupted then the new interrupt is queued rather than interrupting the current interrupt handler. In Linux, this is implemented with the help of a signal. On Windows, it might be possible to implement using the combination of &lt;code&gt;SuspendThread&lt;/code&gt; and &lt;code&gt;SetThreadContext&lt;/code&gt; to manipulate the thread state.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terminate-thread&lt;/code&gt; forcibly terminates a thread. Thread termination is based on thread interruption: a thread is interrupted with a special function that unwinds the stack and exits from the thread.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, the timers are based on interrupts. A timer is a facility to periodically call a function in a specified thread (or in a new thread).&lt;/p&gt;
&lt;p&gt;The main synchronization object used by SBCL is the futex. On Linux, it is implemented as a native Linux futex and is called a &amp;ldquo;lutex&amp;rdquo;. In a nutshell, futex is a combination of a mutex with a conditional variable, i.e. it protects the data from concurrent access and allows to wait for changes in the data. Waiting for changes is used, for example, inside the SBCL to wait for the thread state to change. On Windows, there are no conditional variables (or rather, they are available but only in the newest versions of Windows), so we will need to implement futexes based on the primitives that we have (for example, a critical section and an event). One peculiarity of SBCL is that the futexes themselves are not exposed, but rather the synchronization functions accept the pointer to the data being protected by the futex. This allows not dumping the futexes when saving the image to the disk and in general to disregard their initialization and finalization which somewhat simplifies their implementation.&lt;/p&gt;
</description>
		</item>
		<item>
			<title>SLIME is getting better</title>
			<link>https://dmitryvk.me/posts/2010/slime/</link>
			<pubDate>Tue, 09 Feb 2010 07:06:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/slime/</guid>
			<description>&lt;p&gt;SLIME is getting better. Today I discovered that it shows the arguments for the local functions defined with &lt;code&gt;flet&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I.e., given the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;foobar&lt;/span&gt; ()
  (&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;flet&lt;/span&gt; ((&lt;span style=&#34;color:#008080&#34;&gt;bar&lt;/span&gt; (&lt;span style=&#34;color:#008080&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;z&lt;/span&gt;) (&lt;span style=&#34;color:#900;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;z&lt;/span&gt;)))
    (&lt;span style=&#34;color:#008080&#34;&gt;bar&lt;/span&gt; )))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;if I put the cursor after the &lt;code&gt;(bar &lt;/code&gt;, the minibuffer will display &lt;code&gt;(bar x y z)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;screenshot.png&#34; alt=&#34;screenshot&#34;&gt;&lt;/p&gt;
</description>
		</item>
		<item>
			<title>Summary of recent changes in cl-gtk2</title>
			<link>https://dmitryvk.me/posts/2010/cl-gtk2-recent-changes/</link>
			<pubDate>Tue, 26 Jan 2010 00:28:00 +0300</pubDate>
			<author>Kalyanov.Dmitry@gmail.com (Dmitry Kalyanov)</author>
			<guid isPermaLink="true">https://dmitryvk.me/posts/2010/cl-gtk2-recent-changes/</guid>
			<description>&lt;p&gt;I&#39;ve been able to make some time to work on cl-gtk2 and as a result, I&#39;ve published a few changes. Below is a short summary of them.&lt;/p&gt;
&lt;h1 id=&#34;loadtime-checking-for-minimum-versions-of-libraries&#34;&gt;Load-time checking for minimum versions of libraries&lt;/h1&gt;
&lt;p&gt;During loading, cl-gtk2 now checks versions of the libraries and generates a load-time error if the version is too old. This should help to improve error diagnostics in such cases.&lt;/p&gt;
&lt;h1 id=&#34;support-for-several-versions-of-gtk&#34;&gt;Support for several versions of Gtk+&lt;/h1&gt;
&lt;p&gt;Added rudimentary support for multiple Gtk+ versions. During loading cl-gtk2 adds into the &lt;code&gt;*features*&lt;/code&gt; the symbols that correspond to the versions of glib and Gtk+, and the rest code may use them for conditional compilation of classes, functions, and methods. So if you try to load cl-gtk2 with, say, a Gtk+-2.18 installed, you will be able to access classes from Gtk+-2.18. But if later you upgrade to the later Gtk+ version you will have to recompile the cl-gtk2.&lt;/p&gt;
&lt;h1 id=&#34;improved-demo-program&#34;&gt;Improved demo program&lt;/h1&gt;
&lt;p&gt;I&#39;ve slightly improved the demonstration program &lt;code&gt;gtk-demo:demo&lt;/code&gt; included in the cl-gtk2. Now it looks like a text page with links to various examples:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;demo.png&#34; alt=&#34;screenshot&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;working-with-the-applications-main-loop&#34;&gt;Working with the application&#39;s main loop&lt;/h1&gt;
&lt;p&gt;Now the functions &lt;code&gt;ensure-gtk-main&lt;/code&gt;, &lt;code&gt;leave-gtk-main&lt;/code&gt;, &lt;code&gt;join-gtk-main&lt;/code&gt;, and the macro &lt;code&gt;with-main-loop&lt;/code&gt; work similarly in both the single-threaded and multithreaded Lisp implementations.&lt;/p&gt;
&lt;p&gt;They should be used in the following manner.&lt;/p&gt;
&lt;p&gt;The main function would contain the code similar to the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-lisp&#34; data-lang=&#34;lisp&#34;&gt;(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;run&lt;/span&gt; ()
  (&lt;span style=&#34;color:#008080&#34;&gt;within-main-loop&lt;/span&gt;
    (&lt;span style=&#34;color:#008080&#34;&gt;your-application-code&lt;/span&gt;) &lt;span style=&#34;color:#998;font-style:italic&#34;&gt;;; at some point, the application will call leave-gtk-main&lt;/span&gt;
  ))
(&lt;span style=&#34;color:#0086b3&#34;&gt;defun&lt;/span&gt; &lt;span style=&#34;color:#008080&#34;&gt;main&lt;/span&gt; ()
  (&lt;span style=&#34;color:#008080&#34;&gt;run&lt;/span&gt;)
  (&lt;span style=&#34;color:#008080&#34;&gt;join-gtk-main&lt;/span&gt;)
  (&lt;span style=&#34;color:#008080&#34;&gt;quit&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then the &lt;code&gt;main&lt;/code&gt; function will return when the application invokes the &lt;code&gt;leave-gtk-main&lt;/code&gt; function and the application will exit. The &lt;code&gt;main&lt;/code&gt; function like this can be used as a top-level function when saving the image or when running a script, and the &lt;code&gt;run&lt;/code&gt; function may be used to invoke the application from the REPL during development - it will work in the background and you may incrementally add the code to the application.&lt;/p&gt;
&lt;h1 id=&#34;threadsafe-finalization-of-gboxed-instances&#34;&gt;Thread-safe finalization of GBoxed instances&lt;/h1&gt;
&lt;p&gt;I&#39;ve made the finalization of GBoxed instances thread-safe and fixed a couple of bugs related to that.&lt;/p&gt;
</description>
		</item>
	</channel>
</rss>
