<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="/rss/rssxslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>ZpqrtBnk</title>
    <link>http://www.zpqrtbnk.net/</link>
    <description>ZpqrtBnk - Software Ektropist</description>
    <generator>ZpqrtBnk + Umbraco</generator>
    <item>
      <guid isPermaLink="false">11391</guid>
      <link>http://www.zpqrtbnk.net/posts/careful-with-that-struct/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>Careful with that Struct</title>
      <description>&lt;p&gt;&lt;em&gt;Method Chaining&lt;/em&gt; is a general pattern where an object class implements methods that alter the state of the object, &lt;em&gt;and&lt;/em&gt; return the current instance, thus allowing code such as:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;var c = new C();
c.ChangeThis(123).ChangeThat(456);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For instance, this very minimal C# example:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;class C
{
  private string? _s;
  
  public C Change(string s)
  {
    _s = s;
    return this;
  }

  public override string ToString() =&amp;gt; _s;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Could be used with the following results:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;var c = new C();
c.Change(&amp;quot;a&amp;quot;);
Console.WriteLine(c); // writes 'a'
c.Change(&amp;quot;b&amp;quot;).Change(&amp;quot;c&amp;quot;);
Console.WriteLine(c); // writes 'c'
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let's say we want to be clever and for some reason we decide to implement the pattern on a mutable &lt;code&gt;struct&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;struct C
{
  private string? _s;
  
  public C Change(string s)
  {
    _s = s;
    return this;
  }

  public override string ToString() =&amp;gt; _s;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Can you predict the output of this code?&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;var c = new C();
c.Change(&amp;quot;a&amp;quot;);
Console.WriteLine(c); // writes 'a'
c.Change(&amp;quot;b&amp;quot;).Change(&amp;quot;c&amp;quot;);
Console.WriteLine(c); // writes ??
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Turns out, but the second write &lt;strong&gt;will be 'b'&lt;/strong&gt; not 'c'. How come?&lt;/p&gt;
&lt;p&gt;It goes like this. We know that &lt;code&gt;struct&lt;/code&gt; are passed around by value. More precisely, they are &lt;em&gt;copied&lt;/em&gt; around when passed or returned to functions. Except of course for their own functions, which act on the &lt;code&gt;struct&lt;/code&gt; itself. So when the &lt;code&gt;Change&lt;/code&gt; method is invoked directly on the &lt;code&gt;c&lt;/code&gt; variable, it operates on the &lt;em&gt;actual&lt;/em&gt; structure owned by the &lt;code&gt;c&lt;/code&gt; variable, and thus mutate it. This is why the first line writes 'a'.&lt;/p&gt;
&lt;p&gt;However, the &lt;code&gt;Change&lt;/code&gt; method also returns a &lt;code&gt;C&lt;/code&gt; instance. And we just reminded ourselves that &lt;code&gt;struct&lt;/code&gt; instances are copied around, so &lt;code&gt;Change&lt;/code&gt; returns a &lt;em&gt;copy&lt;/em&gt; of the structure owned by the &lt;code&gt;c&lt;/code&gt; variable. So after the &lt;code&gt;c.Change(&amp;quot;b&amp;quot;)&lt;/code&gt; call, &lt;em&gt;both&lt;/em&gt; the structure in the &lt;code&gt;c&lt;/code&gt; variable, and its copy, have a 'b' value.&lt;/p&gt;
&lt;p&gt;But the chained method then operates on the copy! The copy is modified, and the result is ignored. The original structure owned by the &lt;code&gt;c&lt;/code&gt; variable is &lt;em&gt;not&lt;/em&gt; modified a second time. The second line writes 'b'.&lt;/p&gt;
&lt;p&gt;Of course, if we do not ignore the returned value, things work as &amp;quot;expected&amp;quot;:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;c = c.Change(&amp;quot;b&amp;quot;).Change(&amp;quot;c&amp;quot;);
Console.WriteLine(c); // writes 'c'
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So what is the conclusion here? Of course, it could be &amp;quot;do not mutate structs&amp;quot;, which certainly is a valid general principle, but maybe a bit radical. On the other hand, it seems fairly reasonable to recommend against chaining methods for mutable structs.&lt;/p&gt;
</description>
      <pubDate>Sat, 10 Jan 2026 16:00:00 Z</pubDate>
      <a10:updated>2026-01-10T16:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11364</guid>
      <link>http://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e04/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>Tales of FPGA - Road to SDRAM - E04</title>
      <description>&lt;p&gt;This post is the fourth one of a serie:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e01/"&gt;Episode 1&lt;/a&gt; presents what FPGA are and how to control them&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e02/"&gt;Episode 2&lt;/a&gt; highlights the importance of time in FPGAs&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e03/"&gt;Episode 3&lt;/a&gt; presents the different types of RAM&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ultimate goal of this serie of posts is to provide a simple working example of a design that can reliably access the SDRAM chip on a &lt;a href="https://digilent.com/reference/programmable-logic/arty-s7/start"&gt;Digilent Arty S7&lt;/a&gt; FPGA development board.&lt;/p&gt;
&lt;p&gt;And now, the time has come to actually try to implement access to that SDRAM chip. Of course there is the easy way: Xilinx provides an IP, the &lt;a href="https://www.xilinx.com/products/intellectual-property/mig.html"&gt;MIG&lt;/a&gt; (Memory Interface Generator), that just does it. OK, its &lt;a href="https://docs.amd.com/v/u/en-US/ug086"&gt;documentation&lt;/a&gt; is about 600 pages so maybe &amp;quot;just&amp;quot; here is a gross simplification, but nevertheless.&lt;/p&gt;
&lt;p&gt;It essentially generates a module that, to keep things simple, expose an address bus, a data bus, and a few control lines. On the diagram below, the block to the left is you, the user. The block on the right is the SDRAM chip. The block in the middle is magic.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/5k3bpv2s/mig-mw-600.png?hmac=16264b0795135b8617f4008098f8a2449dd1e476d8f7e991da4d02e66b03b623" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;By carefully following the rules, I managed to produce a complete design that can write-then-read-back data to/from the SDRAM, and blink a LED if everything is OK. Done.&lt;/p&gt;
&lt;p&gt;However, (a) that IP is very generic and therefore has latencies introduced here and there. In other words, it is not giving you access to the SDRAM at the full speed it could support. And of course, (b) it is not fun.&lt;/p&gt;
&lt;p&gt;Which takes us to the alternative: read the DDR3 protocol specifications, and implement them. Sorry to disapoint, but I am &lt;em&gt;not&lt;/em&gt; going to enter into the details of DDR3 here. It is &lt;em&gt;quite&lt;/em&gt; hairy and well documented. Google is your friend.&lt;/p&gt;
&lt;p&gt;Let us just say that the protocol is mostly serial, so serialization and de-serialization of the data bus is involved. Reading one address implies sending a stream of commands to select the correct bank and row, then receiving the value.&lt;/p&gt;
&lt;p&gt;It took me quite some time (and more), but I managed to implement a complete memory controller that Vivado would happily build and simulate. As in: we can observe the lines going to the (simulated) SDRAM chip change according to the specs, the chip behave just as it should, data goes in and out.&lt;/p&gt;
&lt;p&gt;In the simulator.&lt;/p&gt;
&lt;h4&gt;#Fail&lt;/h4&gt;
&lt;p&gt;Once I tried to synthetize and implement the design on silicon, things turned pretty ugly. Vivado complained about timing issues. &lt;em&gt;Lots&lt;/em&gt; of timing issues. As in, thousands of them. There was not a single part of the design that did not make it cringe.&lt;/p&gt;
&lt;p&gt;Of course, sending the design to the actual physical board plainly failed to work and, as we have explained before, there is little we can observe. No debugger, nothing. Only this: it works on paper, it works in the simulator, it fails in Real Life.&lt;/p&gt;
&lt;p&gt;Bummer. My idea was to get it to work, and sort of brag about how, yes, I have been able to make it work. Unfortunately (and that explains the delay between this article and the previous one) I must face reality: I failed.&lt;/p&gt;
&lt;p&gt;Of course I wondered how Xilinx thought we were supposed to access the SDRAM chip.&lt;/p&gt;
&lt;h4&gt;The Black Box from Hell&lt;/h4&gt;
&lt;p&gt;So I started to break that black box open, in order to learn what magic tricks allowed it to work. And here is what I learned: SDRAM clocks are &lt;em&gt;fast&lt;/em&gt;, as in, above 600MHz. And at that kind of speed, &lt;em&gt;everything&lt;/em&gt; matters. If you have an 8-bit bus to the SDRAM chip, the actual &lt;em&gt;placement&lt;/em&gt; of the logic controlling each bit on the FPGA chip makes a difference. Even the &lt;em&gt;length&lt;/em&gt; of the path between the FPGA chip and the SDRAM chip matters. Oh, even the &lt;em&gt;temperature&lt;/em&gt; of the SDRAM chip has an impact, and you are supposed to monitor it and re-calibrate everything when it changes.&lt;/p&gt;
&lt;p&gt;And Xilinx's IP is a powerfull wizard indeed, which not only generates Verilog code, but also additional files that position each specific gate and component at a precise place on the die, and constantly monitors the temperatures, the delays, etc. and adjust for them.&lt;/p&gt;
&lt;p&gt;There is no way I want to understand, nor replicate, all this stuff. I don't really want to deal with the physical world&amp;mdash;I am happy with the logical one. Plus, it is kind of a moot exercise that Xilinx engineers have already solved.&lt;/p&gt;
&lt;p&gt;And yet, it is frustrating.&lt;/p&gt;
&lt;h4&gt;Enters the PHY&lt;/h4&gt;
&lt;p&gt;I wanted to find some sort of in-between solution, which would give me control over the DDR3 protocol, yet deal with all the physical layer for me. And it turned out that Xilinx design sort of provides this. Internally, the black box is a pipeline of smaller black boxes:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/xjpnk03q/phy-mw-600.png?hmac=064ba785aa67f44cd060e5ab2795521a96ce3fe751839fc345a15437d48c130d" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;And it turns out that the box named &amp;quot;PHY Interface&amp;quot; on this diagram implements precisely this: the complete control of the nitty-gritty of the physical layer, plenty of components such as &amp;quot;phasers&amp;quot; which are used to keep multiple signals in sync when for instance temperature changes would cause them to drift apart.&lt;/p&gt;
&lt;p&gt;Interesting for sure, but way too close to the physical world for my liking.&lt;/p&gt;
&lt;p&gt;Extracting the PHY layer from the global MIG IP is not an easy task, as it seems it was never meant (by Xilinx engineers) to be extracted &lt;em&gt;for real&lt;/em&gt;. Oh, and the code is not exactly as clean as the diagram presents it, and even figuring out what is or is not in the PHY is not obvious.&lt;/p&gt;
&lt;p&gt;Nevertheless, this has allowed me to produce a module that can reliably read and write commands and data to the SDRAM chip, as fast as the DDR3 protocol allows, and nothing more. A bit more work let me re-wire my original memory controller on top of this module, and voila, it all worked.&lt;/p&gt;
&lt;p&gt;TADA!&lt;/p&gt;
&lt;p&gt;And no, I will not describe it here. It would be pointlessly complex, and probably of no interest if you do not plan to use it yourself. That being said, the entire code is available on my &lt;a href="https://github.com/zpqrtbnk/road-to-sdram"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Now what?&lt;/h4&gt;
&lt;p&gt;The reason for all this exercise is that I have implemented, on the FPGA, a SOC (system-on-chip) composed of a custom 8-bit CPU loosely extrapolated from the 6502/6809 family of chips, along with 64KB of RAM, VGA, and PS/2 keyboard.&lt;/p&gt;
&lt;p&gt;It works quite well but currently only runs within its 64KB of RAM, which may not be enough if I want to, say, implement a TCP network stack and a small HTTP server. Having access to the full 256MB of the SDRAM chip would certainly help.&lt;/p&gt;
&lt;p&gt;Hence our next challenge: how does an 8-bit CPU with a 16-bit address bus (i.e. a 64KB address space) handle a 256MB memory space in a nice and efficient way? Want to read about MMUs (memory management units), memory paging and banking, segments? Stay tuned!&lt;/p&gt;
</description>
      <pubDate>Sun, 05 May 2024 20:00:00 Z</pubDate>
      <a10:updated>2024-05-05T20:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11386</guid>
      <link>http://www.zpqrtbnk.net/posts/taskcompletionsource-pitfalls/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>TaskCompletionSource Pitfalls</title>
      <description>&lt;p&gt;Imagine you are implementing a client for a server that performs an operation on some data, and that operation is totally asynchronous, and the server has only &lt;em&gt;one&lt;/em&gt; connection to it.&lt;/p&gt;
&lt;p&gt;Contrary to an HTTP server, where a new connection is opened for each request (or, where requests are queued on one connection), requests must be pushed to the server with some sort of unique identifier, and the server will push responses back in whatever order it produces them.&lt;/p&gt;
&lt;p&gt;Let us try to implement the client API:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task&amp;lt;Response&amp;gt; SubmitRequestAsync(Request request)
{
    await server.SendRequestAsync(request);

    // now what?
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here, we have to return a &lt;code&gt;Task&amp;lt;Response&amp;gt;&lt;/code&gt; that represents the client waiting for the response... but what shall we be waiting on? Due to the full asynchronous nature of the server, we probably want to store the request in some sort of lookup table, and then wait for the corresponding response:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task&amp;lt;Response&amp;gt; SubmitRequestAsync(Request request)
{
    await server.SendRequestAsync(request);

    _requests[request.UniqueID] = request;

    // now what?
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We need a background task that listens on the connection and receive responses:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task HandleResponses()
{
    while (true)
    {
        var response = await server.ReceiveResponseAsync();

        // now what?
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Still, what should the &lt;code&gt;SubmitRequestAsync&lt;/code&gt; return, that we could &lt;code&gt;await&lt;/code&gt;? And how should the &lt;code&gt;HandleResponse&lt;/code&gt; method complete the API call?&lt;/p&gt;
&lt;h4&gt;TaskCompletionSource&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;TaskCompletionSource&lt;/code&gt; is a nice feature of .NET that allows a developer to create &amp;quot;something that creates a &lt;code&gt;Task&lt;/code&gt;&amp;quot; and then explicitely decide when to complete, cancel or fail that &lt;code&gt;Task&lt;/code&gt;. Using a completion source, we can finalize our API:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task&amp;lt;Response&amp;gt; SubmitRequestAsync(Request request)
{
    await server.SendRequestAsync(request);

    var completion = new TaskCompletionSource&amp;lt;Response&amp;gt;();

    _requests[request.UniqueID] = request;
    _completions[request.UniqueID] = completion;

    return completion.Task;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here, we create a completion source, and return its &lt;code&gt;Task&lt;/code&gt;. This is a &amp;quot;logical&amp;quot; task: there is no executing code corresponding to it. It just represent &amp;quot;the execution of something&amp;quot;. And that execution would be completed by the background task:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task HandleResponses()
{
    while (true)
    {
        var response = await server.ReceiveResponseAsync();
        var completion = _completions[response.UniqueID];
        completion.TrySetResult(response);        
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The task retrieves the completion source corresponding to the unique request identifier, and &lt;em&gt;completes&lt;/em&gt; it by assigning it a result. In a more elaborate scenario, it could also fail it by assigning it an exception, or even cancel it. &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;NOTE: this is a simplified version of the code. In real life, we would need to ensure thread safety, remove requests and completions from their lookup tables, etc.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Yes, but&lt;/h4&gt;
&lt;p&gt;We could end the article here, but... there's a &lt;em&gt;but&lt;/em&gt;. What do you think happens when &lt;code&gt;completion.TrySetResult(response)&lt;/code&gt; is invoked? Intuitively, we assume that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;TrySetResult&lt;/code&gt; returns from the call and the &lt;code&gt;while&lt;/code&gt; loop repeats;&lt;/li&gt;
&lt;li&gt;Whatever code was awaiting the completion's &lt;code&gt;Task&lt;/code&gt; is unlocked and starts running.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words, invoking &lt;code&gt;TrySetResults&lt;/code&gt; fork a new parallel code execution path that resumes whatever code was &lt;code&gt;await&lt;/code&gt;-ing the completion's &lt;code&gt;Task&lt;/code&gt;, while the main code execution path continues looping the &lt;code&gt;while&lt;/code&gt; loop.&lt;/p&gt;
&lt;p&gt;However&amp;mdash;and here is the &lt;em&gt;but&lt;/em&gt;&amp;mdash;.NET tries to optimize asynchronous calls to avoid unnecessary and expensive management of tasks and threads. You have probably heard that when invoking the following method, the call to &lt;code&gt;DoSomethingElse&lt;/code&gt; will run immediately and synchronously, and that the method will only return a &lt;code&gt;Task&lt;/code&gt; when it encounters the first &lt;code&gt;await&lt;/code&gt; statement:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task DoSomething()
{
    DoSomethingElse();
    await DoYetAnotherThing();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It turns out that the very same thing happens with &lt;code&gt;TrySetResult&lt;/code&gt;. .NET will immediately run the code that is &lt;code&gt;await&lt;/code&gt;-ing on the completion's &lt;code&gt;Task&lt;/code&gt;, and the call to &lt;code&gt;TrySetResult&lt;/code&gt; will only complete after either that code is done running, or an &lt;code&gt;await&lt;/code&gt; statement is encountered.&lt;/p&gt;
&lt;h4&gt;And then it all fails&lt;/h4&gt;
&lt;p&gt;Now look at the following code:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task HandleResponses()
{
    while (true)
    {
        var response = await server.ReceiveResponseAsync();
        AquireSemaphore();
        var completion = _completions[response.UniqueID];
        completion.TrySetResult(response);        
        ReleaseSemaphore();
    }
}

public async Task UseTheAPI()
{
    var response = await SubmitRequestAsync(request);
    AquireSemaphore();
    // do something with the response
    ReleaseSemaphore();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What do you think will happen? Spoiler: it will deadlock. The call to &lt;code&gt;TrySetResult&lt;/code&gt; will complete the &lt;code&gt;SubmitRequestAsync&lt;/code&gt; call and flow and continue the &lt;code&gt;UseTheAPI&lt;/code&gt; method. It will try to run &lt;code&gt;AquireSemaphore&lt;/code&gt; in &lt;code&gt;UseTheAPI&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; returning, and will fail to get the semaphore, because it has already been acquired. It will never return, and never release the semaphore, and everything hangs.&lt;/p&gt;
&lt;p&gt;In other words: invoking &lt;code&gt;TrySetResult&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a fire-and-forget thing. In &lt;em&gt;most cases&lt;/em&gt; it will be OK, but in some situation it can lead to deadlocks and other oddities, where &lt;em&gt;a lot&lt;/em&gt; happens between the moment &lt;code&gt;TrySetResult&lt;/code&gt; is invoked and the moment it returns.&lt;/p&gt;
&lt;h4&gt;Uh, what shall we do?&lt;/h4&gt;
&lt;p&gt;In some situations, we really don't know what may be &lt;code&gt;await&lt;/code&gt;-ing the completion's &lt;code&gt;Task&lt;/code&gt;. What we want is a way to tell .NET: don't be clever. Submit whatever is &lt;code&gt;await&lt;/code&gt;-ing to the thread pool and return immediately. Run it all on separate tasks. It &lt;em&gt;may&lt;/em&gt; be a little more expensive, but at least invoking &lt;code&gt;TrySetResult&lt;/code&gt; would become deterministic.&lt;/p&gt;
&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; an option to do this, but it is not a &lt;code&gt;TrySetResult&lt;/code&gt; option. Instead, it needs to be specified when creating the completion souce. The class constructor has an overload that supports a &lt;code&gt;TaskCreationOptions&lt;/code&gt; that can be used to indicate how the tasks resulting from &lt;code&gt;TrySetResult&lt;/code&gt; are supposed to run.&lt;/p&gt;
&lt;p&gt;Especially, &lt;code&gt;TaskCreationOptions.RunContinuationsAsynchronously&lt;/code&gt; specifies that &amp;quot;continuations added to the current task [are] to be executed asynchronously.&amp;quot; We can create our continuation as such:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;var completion = new TaskCompletionSource&amp;lt;Response&amp;gt;(
    TaskCreationOptions.RunContinuationsAsynchronously
);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When &lt;code&gt;TrySetResult&lt;/code&gt; is invoked, it submits all the continuations on the completion's &lt;code&gt;Task&lt;/code&gt; (i.e. all code &lt;code&gt;await&lt;/code&gt;-ing that task) on the thread pool for execution, instead of running them, and returns immediately.&lt;/p&gt;
&lt;h4&gt;Nice, why is this not the default?&lt;/h4&gt;
&lt;p&gt;Because in most cases, this is an overkill. Whenever &lt;code&gt;TaskCompletionSource&lt;/code&gt; instances are used in simple and controlled environment, everything &lt;em&gt;should&lt;/em&gt; be OK and it's better to let .NET optimize everything.&lt;/p&gt;
&lt;p&gt;Nevertheless, it is good to be aware of this pitfall.&lt;/p&gt;
</description>
      <pubDate>Sun, 14 May 2023 16:00:00 Z</pubDate>
      <a10:updated>2023-05-14T16:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11361</guid>
      <link>http://www.zpqrtbnk.net/posts/faster-github-pr-check-time-with-multi-level-matrix-strategy/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>Faster GitHub PR check time with multi-level matrix strategy</title>
      <description>&lt;p&gt;The Hazelcast .NET&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; Client is provided as a library that is supported on .NET (Framework) version 4.6.2 to 4.8, .NET (Core) 3.1, and .NET (Just .NET) 5.0 and 6.0. For .NET Core and Just .NET, the library is supported both on Windows and on Linux. This means that we want to run our complete tests suite on both platforms, for each supported .NET version.&lt;/p&gt;
&lt;p&gt;Originally, we defined a &lt;em&gt;Build PR&lt;/em&gt; workflow that would trigger on each PR and build and run the tests for each .NET version supported by the platform, one after another. In order to test both platforms, we used an OS matrix strategy:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Build PR
on: pull_request

jobs:
  build-pr:
    name: Build PR (${{ matrix.os }})
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [ ubuntu-latest, windows-latest ]

    steps:
    - name: Build and Test the PR
      (etc)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Thanks to this, on each PR, two jobs would run in parallel: one for Linux, and one for Windows. However, on each platform, the tests for each .NET version would run sequentially. And thus... if the complete tests suite takes about 20 minutes to run, the Windows job would take &lt;code&gt;net462&lt;/code&gt; + &lt;code&gt;net48&lt;/code&gt; + &lt;code&gt;netcoreapp3.1&lt;/code&gt; + &lt;code&gt;net5.0&lt;/code&gt; + &lt;code&gt;net6.0&lt;/code&gt; = 5 times 20 minutes, or 1h40. Which is quite a lot of time to validate a PR.&lt;/p&gt;
&lt;h4&gt;Entering the Second Dimension&lt;/h4&gt;
&lt;p&gt;We want to reduce that time, and the idea is to parallelize each .NET version, in addition to platforms. On each PR, we would fork one job for .NET 5.0 on Linux, one job for .NET 6.0 on Linux, one job for .NET 4.8 on Windows, etc. The total build time would be approximatively the build time of &lt;em&gt;one&lt;/em&gt; version or, in our example above, 20 minutes instead of 1h40.&lt;/p&gt;
&lt;p&gt;GitHub supports 2-dimensions matrixes. For instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    matrix:
      os: [ ubuntu-latest, windows-latest ]
      dotnet: [ net5.0, net6.0 ]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In our situation, however, the list of versions to put in the &lt;code&gt;dotnet&lt;/code&gt; dimension if not fixed and actually depends on the OS. We would need to write something akin to the following code, where &lt;code&gt;get_dotnet_version&lt;/code&gt; would be a function returning the .NET version corresponding to the OS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    matrix:
      os: [ ubuntu-latest, windows-latest ]
      dotnet: get_dotnet_versions(matrix.os)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alas, GitHub does not support that type of construct. The only thing it supports is referencing a variable, such as an input, in the matrix. So we would need to be able to produce a unique variable, and yet its value would depend on &lt;code&gt;matrix.os&lt;/code&gt;... again, that type of construct is not supported. All in all, I could not find a way to get one matrix dimension to depend on the other, within one workflow.&lt;/p&gt;
&lt;h4&gt;Divide and Conquer&lt;/h4&gt;
&lt;p&gt;Now... what-if instead of trying to do everything in one workflow, we used two? Our first workflow looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jobs:
  getversions:
    runs-on: ${{ matrix.os }}

    strategy:
      matrix:
        os: [ ubuntu-latest, windows-latest ]

    outputs:
      # beware! this cannot be dynamic = must match the OS matrix
      versions-ubuntu-latest: ${{ steps.getversions.outputs.versions-ubuntu-latest }}
      versions-windows-latest: ${{ steps.getversions.outputs.versions-windows-latest }}

    steps:
    - name: Determine DotNet Versions
      id: getversions
      shell: bash
      run: |
        VERSIONS=$(....)
        echo &amp;quot;::set-output name=versions-${{ matrix.os }}::$VERSIONS&amp;quot;

  buildtest:
    name: Build&amp;amp;Test ${{ matrix.os }}
    needs: getversions
    strategy:
      fail-fast: false
      matrix:
        os: [ ubuntu-latest, windows-latest ]
    uses: ./.github/workflows/build-pr-on.yml
    secrets: inherit
    with:
      os: ${{ matrix.os }}
      versions: ${{ needs.getversions.outputs[format('versions-{0}', matrix.os)] }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let's go through this workflow. It contains two jobs, &lt;code&gt;getversions&lt;/code&gt; and &lt;code&gt;buildtest&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;The first job, &lt;code&gt;getversions&lt;/code&gt;, runs a unique step that determines the versions based on the platform, and sets a job output variable accordingly. That variable contains a JSON list of versions, e.g. &lt;code&gt;[ &amp;quot;net462&amp;quot;, &amp;quot;net48&amp;quot; ]&lt;/code&gt;. Actually, it sets one job output per platform, and I could not find a way to avoid hard-coding the platform names.&lt;/p&gt;
&lt;p&gt;The second job, &lt;code&gt;buildtest&lt;/code&gt;, does not run any steps, but instead triggers another workflow, passing two input parameters: the platform, and the list of versions. And &lt;em&gt;this&lt;/em&gt; is where we manage to specify versions that depend on the platform.&lt;/p&gt;
&lt;p&gt;And then, the magic happens in that other workflow. First, in order to be &amp;quot;callable&amp;quot; with input parameters, it requires this &lt;code&gt;on&lt;/code&gt; statement:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;on: 
  workflow_call:
    inputs:
      os:
        required: true
        type: string
      versions:
        required: true
        type: string
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then its job is defined as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jobs:
  buildtest:
    name: ${{ matrix.fwk }}
    runs-on: ${{ inputs.os }}
    strategy:
      fail-fast: false
      matrix:
        version: ${{ fromJson(inputs.versions) }}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And there we have it: a build and test job that runs on the specified platform, for each specified versions. The last piece of the puzzle consists in wrapping in all into one single conclusion point. This is done via an additional job in the first workflow:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;report:
    name: Build&amp;amp;Test Result
    runs-on: ubuntu-latest
    if: always()
    needs: buildtest
    steps:
    - name: report
      shell: bash
      run: |
        if [ &amp;quot;${{ needs.buildtest.conclusion }}&amp;quot; == &amp;quot;success&amp;quot; ]; then
          echo &amp;quot;All Build&amp;amp;Test checks completed successfully.&amp;quot;
        else
          echo &amp;quot;At least one Build&amp;amp;Test check has failed.&amp;quot;
          echo &amp;quot;::error::At least one Build&amp;amp;Test check has failed.&amp;quot;
        fi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This job &amp;quot;needs&amp;quot; the &lt;code&gt;buildtest&lt;/code&gt; job, in other words it will only run once all our forked build &amp;amp; test jobs have completed. It always run, and succeeds or fails depending on the outputs of all the forked jobs. This means that this is what we see in GitHub actions:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/2ccik3do/sshot-mw-600.png?hmac=f80270f36a51bcb6457d750917d536f75af92cc6672d4a0927cb8e63cc0756e3" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The block to the left shows the two jobs that run, on per platform, and figure out the framework versions for each platform. The center block shows each combination of platform / version build - they all run in parallel. Finally, the block to the right shows the global status of the build.&lt;/p&gt;
&lt;p&gt;That last &amp;quot;Build&amp;amp;Test Result&amp;quot; block can be used as a required check in our GitHub branch configuration, thus ensuring that &lt;em&gt;all&lt;/em&gt; test combinations must be successful before any PR can be merged. &lt;/p&gt;
&lt;p&gt;All in about 20 minutes, not 1h40!&lt;/p&gt;

&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;or maybe it is the &amp;quot;Hazelcast dotnet Client&amp;quot; or &amp;quot;Hazelcast Dotnet Client&amp;quot;, depending on the success of the &lt;a href="https://twitter.com/hashtag/dropthedot"&gt;#dropTheDot&lt;/a&gt; movement initiated by &lt;a href="https://twitter.com/buhakmeh"&gt;Khalid&lt;/a&gt; at a time the .NET Drama Advisory (or should it be the Dotnet Drama Advisory) was pretty low and he got bored.&amp;nbsp;&lt;a href="#fnref:1" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Mon, 26 Sep 2022 12:40:00 Z</pubDate>
      <a10:updated>2022-09-26T12:40:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11322</guid>
      <link>http://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e03/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>Tales of FPGA - Road to SDRAM - E03</title>
      <description>&lt;p&gt;This post is the third one of a serie which starts with &lt;a href="https://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e01/"&gt;Episode 1&lt;/a&gt;, in which we have presented what FPGA are and how to control them, and continues with &lt;a href="https://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e02/"&gt;Episode 2&lt;/a&gt;, in which we have discovered the importance of &lt;em&gt;time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The ultimate goal of this serie of posts is to provide a simple working example of a design that can reliably access the SDRAM chip on a &lt;a href="https://digilent.com/reference/programmable-logic/arty-s7/start"&gt;Digilent Arty S7&lt;/a&gt; FPGA development board.&lt;/p&gt;
&lt;p&gt;In order to understand &lt;em&gt;why&lt;/em&gt; we want to access that chip, let us first review the different types of RAM that can exist in a computer.&lt;/p&gt;
&lt;h4&gt;SRAM&lt;/h4&gt;
&lt;p&gt;The first and most simple memory type is &lt;em&gt;Static Random Access Memory&lt;/em&gt; (SRAM). It is an array of memory cells and exposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;em&gt;address bus&lt;/em&gt; which selects the cell&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;data bus&lt;/em&gt; which contains the value to write, or the value that was read&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;RW&lt;/em&gt; signal which indicates whether to read or write&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;clock&lt;/em&gt; signal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On each clock signal, depending on the RW signal, the cells specified by the address bus are updated with the value specified by the data bus, &lt;em&gt;or&lt;/em&gt; the data bus is updated with the value contained by the specified cells.&lt;/p&gt;
&lt;p&gt;Each cell (i.e. each bit) is implemented with about six transistors, and is stable, or &lt;em&gt;static&lt;/em&gt;: it keeps its value around for as long as power is supplied. Circuitry is minimal, and it is &lt;em&gt;fast&lt;/em&gt;, as in: it can typically keep up with the CPU speed. In other words, the CPU can request a value on a clock tick, and read that value on the next clock tick.&lt;/p&gt;
&lt;h4&gt;(S)DRAM&lt;/h4&gt;
&lt;p&gt;Unfortunately, due to their transistors count, SRAM cells require a &lt;em&gt;lot&lt;/em&gt; (relatively) of silicon, which implies low density and high costs. For instance, a modern Intel Core i9 CPU carries only about 90KB of SRAM L1 cache per core.&lt;/p&gt;
&lt;p&gt;In order to increase density and lower costs, cells have to be simplified down to the simplest cell, which is composed of only one transistor and one capacitor: this type of cell is at the core of most modern memory types. &lt;/p&gt;
&lt;p&gt;Its drawback is that it is not stable: its capacitor charge leaks and the cell loses its value after a while. Additional circuitry is therefore required to refresh (i.e. access) it periodically. Hence the name: &lt;em&gt;Dynamic Random Access Memory&lt;/em&gt; (DRAM).&lt;/p&gt;
&lt;p&gt;Due to their need to be refreshed, but also their density, DRAM have a different and more complex interface. Cells are organized in &lt;em&gt;banks&lt;/em&gt; and &lt;em&gt;rows&lt;/em&gt; and &lt;em&gt;columns&lt;/em&gt;, which must be selected before any read or write can take place. A read or a write now takes several clock ticks, and more control lines determine which operation to achieve.&lt;/p&gt;
&lt;p&gt;Simple, original DRAM operated asynchronously with the CPU's clock. In order to increase efficiency and throughput, they evolved into &lt;em&gt;Synchronized DRAM&lt;/em&gt; (SDRAM) where everything is timed by the CPU. This allows for more optimizations such as pipelining: for instance, selecting the rows and columns of the next read, while receiving data for the previous read.&lt;/p&gt;
&lt;h4&gt;DDR SDRAM&lt;/h4&gt;
&lt;p&gt;In order to further increase the memory bandwidth and reduce latency, the frequency of the data line would need to increase. However, a higher frequency means more energy consumption and heat&amp;mdash;this is the issue faced by all CPUs today. &lt;/p&gt;
&lt;p&gt;To mitigate these side effects, &lt;em&gt;Double Data Rate (DDR) SDRAM&lt;/em&gt; were introduced: they keep the same frequency, but transfer data on each &lt;em&gt;edge&lt;/em&gt; of the clock, not only on each clock cycle, thus doubling the bandwidth.&lt;/p&gt;
&lt;p&gt;DDR was followed by DDR2, DDR3, etc. standards which add more &amp;quot;tricks&amp;quot; to the SDRAM interface, such as burst reads &amp;amp; writes, all in order to increase the speed of memories.&lt;/p&gt;
&lt;p&gt;Nevertheless, and despite all optimizations, SDRAM simply cannot keep up with modern CPU speeds anymore. The CPU cannot expect to request a value, and get it on the next clock tick, as it did with SRAM when computers had only a few KB of RAM. Modern CPU have to rely on various levels of caches and all sorts of optimizations in order to remain busy while waiting for memory reads and writes.&lt;/p&gt;
&lt;h4&gt;FPGA RAM&lt;/h4&gt;
&lt;p&gt;Now that we have reviewed the different types of memories, let us consider what exists on our FPGA board:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The FPGA chip itself contains some SRAM blocks that can run as fast as the rest of the chip. We have however seen that SRAM is expensive: our FPGA chip carries only about 338KB of RAM.&lt;/li&gt;
&lt;li&gt;A separate chip on the board (the same chip you would find in a PC) provides 256MB of DDR3 SDRAM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Accessing the SRAM blocks is relatively easy. Once instantiated in a design, one &amp;quot;just&amp;quot; needs to drive the address and data busses correctly. And, it is fast. Alas, the total available capacity is quite small.&lt;/p&gt;
&lt;p&gt;Which leads us to the SDRAM chip. However, accessing that chip is an entirely different story, and the DDR3 protocol is a &lt;em&gt;complex beast&lt;/em&gt; to implement. That will be the topic of the next post.&lt;/p&gt;
</description>
      <pubDate>Tue, 13 Sep 2022 12:00:00 Z</pubDate>
      <a10:updated>2022-09-13T12:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11320</guid>
      <link>http://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e02/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>Tales of FPGA - Road to SDRAM - E02</title>
      <description>&lt;p&gt;This post is the second one of a serie which starts with &lt;a href="https://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e01/"&gt;Episode 1&lt;/a&gt;, in which we have presented what FPGA are, how to control them, and implicitly discovered their major benefit: they make the physical world rational and clean.&lt;/p&gt;
&lt;p&gt;Indeed, the physical world a.k.a. &amp;quot;reality&amp;quot; is notoriously messy, as anyone who has tried to implement some design with discrete electronic components knows.&lt;/p&gt;
&lt;p&gt;For instance, should we decide that &amp;quot;zero&amp;quot; is +0V and &amp;quot;one&amp;quot; is +5V... there are chances that the transistor-based AND gate that we carefully assembled on our breadboard outputs +4.8V for &amp;quot;one&amp;quot; and not +5V because, imperfections. If we feed that signal into anoter gate, it will &lt;em&gt;probably&lt;/em&gt; be identified as &amp;quot;one&amp;quot;. But if we keep doing this, then at one point we will end up with a +2.6V signal and what is that supposed to mean exactly? &amp;quot;Zero&amp;quot;, or &amp;quot;one&amp;quot;? Our design lacks additional circuitry to ensure that we maintain the correct signal levels everywhere, we feed enough current, etc.&lt;/p&gt;
&lt;p&gt;Another example: these 30 cm of wire flying over our breadboard and carrying a signal at, say, 100MHz? It is an &lt;em&gt;antenna&lt;/em&gt; in the FM radio frequencies. It is going to broadcast that signal, as well as be impacted by existing radio signals on that frequency. Our design may randomly fail and, if carefully examining signals with a scope, we would see all sorts of very weird distortions.&lt;/p&gt;
&lt;p&gt;FPGA have none of this: they are clean and reproducible. We write text files, have them processed by a tool, and end up with a hardware-level design that just works. If we make a mistake, there is no need for rewiring things, going to the shop to buy that one component we are missing, etc. We do not have to worry about radio interferences, current leaks, etc.&lt;/p&gt;
&lt;p&gt;With FPGA, the physical world becomes deterministic.&lt;/p&gt;
&lt;h4&gt;Meet the Enemy&lt;/h4&gt;
&lt;p&gt;And yet, the FPGA designer has one enemy, and this enemy is &lt;em&gt;time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It is convenient to think of a LUT2 as something that immediately updates its output according to its inputs. In reality, it is &lt;em&gt;almost&lt;/em&gt; immediate. In the FPGA chip we are using (a Xilinx Spartan-7 family chip), the delay would be around .15ns or &lt;strong&gt;150ps&lt;/strong&gt;. A flip-flop has a delay of about .55ns or &lt;strong&gt;550ps&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Sure, 150ps is 0.000 000 000 150s and this is &lt;em&gt;very small&lt;/em&gt;. Yet, the period of a 4GHz signal&amp;mdash;a value one can meet in modern CPUs&amp;mdash;is &lt;strong&gt;250ps&lt;/strong&gt;: a very small value too, but one which is very comparable, in scale, to the above delay.&lt;/p&gt;
&lt;p&gt;It is also convenient to think of connections betweens elements as pure electric wires, carrying signals at the speed of light. In reality, signals travels the FPGA die at a slower speed, because connections are not just true electric wires. And then even at the speed of light, electricity only travels about 30cm per ns, or &lt;strong&gt;3mm in 10ps&lt;/strong&gt;, and considering the size of a typical chip die, 3mm might be the distance separating two LUTs.&lt;/p&gt;
&lt;p&gt;Let us see what this means with an example.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/id3kwicj/adder-mw-600.png?hmac=420b704c9858eb1bd87a604344928b896c517fe402b80f4bb1bd2c06ae3da04b" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;This circuit increments a two-bits signal on every clock tick. The new square boxes are &lt;em&gt;flip-flops&lt;/em&gt;: they update their output (the &lt;code&gt;Q&lt;/code&gt; port) to reflect the value of their input (the &lt;code&gt;D&lt;/code&gt; port) on each raising edge of their clock (the &lt;code&gt;C&lt;/code&gt; port). So &lt;code&gt;count&lt;/code&gt; will go &lt;code&gt;00&lt;/code&gt;, &lt;code&gt;01&lt;/code&gt;, &lt;code&gt;10&lt;/code&gt;, &lt;code&gt;11&lt;/code&gt;, &lt;code&gt;00&lt;/code&gt;, &lt;code&gt;01&lt;/code&gt;, etc. each time the clock ticks.&lt;/p&gt;
&lt;p&gt;More precisely, when the clock ticks,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flip-flops update their output to match their input after about .55ns&lt;/li&gt;
&lt;li&gt;Gates update their output to match their inputs after about .15ns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, &lt;code&gt;count_next[1]&lt;/code&gt; will reach its new value after .55 + .15 + .15 = .85ns. This is called the &lt;em&gt;&lt;a href="https://nandland.com/lesson-11-what-is-propagation-delay/"&gt;propagation delay&lt;/a&gt;&lt;/em&gt;. And still, we cannot tick the clock immediately, because the flip-flops demand that the input be stable for some amount of time before the clock ticks: this is call the &lt;em&gt;&lt;a href="https://nandland.com/lesson-12-setup-and-hold-time/"&gt;setup time&lt;/a&gt;&lt;/em&gt;. It is about .05ns in our case. And thus, the clock can only ticks again after .9ns have elapsed.&lt;/p&gt;
&lt;p&gt;We are ignoring the connection delays here. So, let's round it all to &lt;strong&gt;1ns&lt;/strong&gt;. This corresponds to a frequency of &lt;strong&gt;1GHz&lt;/strong&gt;. Not too bad, but this is a &lt;em&gt;very simple&lt;/em&gt; circuit.&lt;/p&gt;
&lt;p&gt;Very quickly, things get complex, and the maximum frequency can fall down to 100MHz or even 10MHz. If we do not respect that constraint, things become completely unpredictable. If we are only slightly too fast, we might not respect the setup time, thus creating a situation called &lt;em&gt;&lt;a href="https://nandland.com/lesson-13-metastability/"&gt;metastability&lt;/a&gt;&lt;/em&gt;: the data coming out of flip-flops may be randomly wrong. And of course, if we are &lt;em&gt;really&lt;/em&gt; too fast, everything becomes random.&lt;/p&gt;
&lt;h4&gt;Know Thy Enemy&lt;/h4&gt;
&lt;p&gt;Tools such as the Vivado IDE do not simply convert code into a network of LUTs, flip-flops, etc. They also decide &lt;em&gt;which&lt;/em&gt; elements to use on the chip (which can contain a few thousands LUTs, for instance), trying to minimize the &lt;em&gt;physical distance&lt;/em&gt; between elements. And then, they process the resulting network and calculate all the propagation times and finaly issue a &lt;em&gt;timing report&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Take the LED blinker from the previous episode. We would tell Vivado that the clock signal comes from &amp;quot;outside&amp;quot; of the chip, actually an oscillator on the development board, which runs at 12MHz. Vivado would report that at 12MHz, everything is fine. There is another oscillator on the board, which runs at 100MHz, and that should be OK too.&lt;/p&gt;
&lt;p&gt;But imagine we have a 1GHz clock on the board: Vivado would definitively build the design (which we can then push to the board) but it would also issue timing warnings, telling us that our design has little chance to work.&lt;/p&gt;
&lt;p&gt;When that happens, for instance when we try to run our carefully crafted CPU at 10MHz and Vivado complains about timings, there are essentially two solutions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slow the clock. Not very satisfactory, but simple enough&lt;/li&gt;
&lt;li&gt;Refactor the design, maybe doing less per clock cycle (see: &lt;a href="https://www.allaboutcircuits.com/technical-articles/why-how-pipelining-in-fpga/"&gt;pipelining&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Were we not supposed to talk about SDRAMs?&lt;/h4&gt;
&lt;p&gt;We were, but that little disgression about time will prove useful in the next episode, where we will present the different types of RAM and see how RAM is essentially dictating time constraints in a modern design.&lt;/p&gt;
&lt;p&gt;To be continued!&lt;/p&gt;
</description>
      <pubDate>Tue, 16 Aug 2022 19:00:00 Z</pubDate>
      <a10:updated>2022-08-16T19:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11314</guid>
      <link>http://www.zpqrtbnk.net/posts/tales-of-fpga-road-to-sdram-e01/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>Tales of FPGA - Road to SDRAM - E01</title>
      <description>&lt;p&gt;This post is the first one of a serie, which aims at providing a simple working example of a design that can reliably access the SDRAM chip on a &lt;a href="https://digilent.com/reference/programmable-logic/arty-s7/start"&gt;Digilent Arty S7&lt;/a&gt; FPGA development board. Indeed, although this board has been out for quite some time now, such a design seems practically impossible to find on the 'net, for reasons we will try to analyze.&lt;/p&gt;
&lt;p&gt;I also mean this serie to be an introduction to FPGA for people who have little idea what they actually are nor how they work. So, even if you do not care about accessing SDRAM on that particular board, you may find it an interesting read. In fact, my interest in FPGA owes a lot to the fact that they help understand the inner working of a CPU, a RAM, and any modern computer.&lt;/p&gt;
&lt;h4&gt;Arty S7?&lt;/h4&gt;
&lt;p&gt;The Arty S7 is an FPGA development board based upon Xilinx' &lt;a href="https://www.xilinx.com/products/silicon-devices/fpga/spartan-7.html"&gt;Spartan-7&lt;/a&gt; series of FPGA chips. It is a cost-effective design packing an FPGA chip, DDR3L memory, buttons, leds, I/O and expansion ports... everything you need to experiment with an FPGA at a reasonable cost (around USD 100.00).&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/d0ikhskl/arty-s7-fit-600x300x1x1-0x0x0x0-75.jpg?hmac=4e9ae5a8b157928fa6adfa0ce49f346760037f1d60a96d2a79efd49bee7c9efe" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;In a way, it is similar to an Arduino board, with the CPU replaced by the FPGA chip.&lt;/p&gt;
&lt;h4&gt;And what is an FPGA chip?&lt;/h4&gt;
&lt;p&gt;An FPGA is a &lt;a href="https://en.wikipedia.org/wiki/Field-programmable_gate_array"&gt;Field Programmable Gate Array&lt;/a&gt;: a semiconductor device based around a matrix of configurable logic blocks, connected via programmable interconnects. The most basic logic block would be, for instance, an AND gate:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/er1fyvcx/and-gate-mw-600.png?hmac=1cb7385922a9b5071ee96e3411a175d76f66a9d32b96a7399da18718ed82287e" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;When any of the gate inputs change, the output is adjusted, after a short inevitable delay. This type of gate can be implemented with a few transistors, and along with the other OR, XOR... gates they are the basic elements of all silicon-based operations.&lt;/p&gt;
&lt;p&gt;In reality, FPGA do not implement AND gates, and their most basic logic block would rather be a &lt;em&gt;2-bit look-up table&lt;/em&gt;, or LUT2. It also has two inputs and one output, and updates its output according to its inputs. But the value of the output is specified by a 2x2 logic table. This way, one single block can be configured to be an AND, OR, XOR... gate.&lt;/p&gt;
&lt;p&gt;And then there are LUT4, LUT6... which follow the same principle only with more inputs. You would also find &lt;a href="https://en.wikipedia.org/wiki/Flip-flop_(electronics)"&gt;flip-flops&lt;/a&gt; which can latch a stable state on a clock signal, oscillators, some type of memories, etc. that you can all configure in the same way one configures the logic table of a LUT2.&lt;/p&gt;
&lt;p&gt;All these blocks are layed out in precise positions on the die of the FPGA chip. And then, there is an interconnect layer which can be configured to wire (pratically) any block input or output with any other block input or output. So you could configure a LUT2 as an AND gate, and wire its output to the input of another LUT2 configured as an OR gate, etc.&lt;/p&gt;
&lt;p&gt;The whole configuration is represented as a blob of binary data which needs to be fed to the FPGA before it can operates. Traditionally, some additional hardware on the development board handle this process and read this blob from Flash memory, or allow the developer to upload it via an USB link.&lt;/p&gt;
&lt;h4&gt;Taking Control&lt;/h4&gt;
&lt;p&gt;FPGA manufacturers provide tools and development environments that let users configure their chips. &lt;a href="https://www.xilinx.com/"&gt;Xilinx&lt;/a&gt;, a major FPGA actor owned by AMD, even have several of them, the most popular (and having a free edition) being the &lt;a href="https://www.xilinx.com/products/design-tools/vivado.html"&gt;Vivado&lt;/a&gt; IDE. These tools support various description languages such as &lt;a href="https://en.wikipedia.org/wiki/VHDL"&gt;VHDL&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Verilog"&gt;Verilog&lt;/a&gt; or its &lt;a href="https://en.wikipedia.org/wiki/SystemVerilog"&gt;SystemVerilog&lt;/a&gt; evolution. These languages are used to specify the FPGA internal configuration, as a set of text files.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;major&lt;/em&gt; difference with traditional programming languages is that all these elements and signals and connections operate concurrently. An FPGA design is a &lt;em&gt;massively parallel&lt;/em&gt; thing.&lt;/p&gt;
&lt;p&gt;This post is certainly not a VHDL nor Verilog tutorial. Let us just say that it all begins with a &lt;em&gt;module&lt;/em&gt; which has inputs and outputs (connected to the actual external pins of the FPGA), along with internal signals, and defines connections between these signals. The following module would for instance act as an AND gate:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module and_gate (
    input logic in_0,
    input logic in_1,
    output logic out
);

    LUT2 #(
        .INIT (4'b1000)    // define the logic table
    )
    LUT2_inst (
        .I0 (in_0),        // wire module input in_0 to LUT2 input I0
        .I1 (in_1),        // wire module input in_1 to LUT2 input I1
        .O (out)           // wire LUT2 output 0 to module output out
    );

endmodule
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The LUT2 logic table is documented as being a 4-bit value with the higher-rank bit (left-most) representing the output value when both inputs are &lt;code&gt;1&lt;/code&gt;, and thus, our LUT2 will act as an AND gate.&lt;/p&gt;
&lt;p&gt;Vivado can then &amp;quot;compile&amp;quot; this design, provided that you also tell it how to wire the inputs and outputs of the module. For instance, inputs could be wired to buttons, and outputs to LEDs. The compiler will determine &lt;em&gt;which&lt;/em&gt; LUT2 to use on the board, and produce the FPGA configuration binary blob, that Vivado can feed to the board via USB. There, done, our first design!&lt;/p&gt;
&lt;p&gt;However, Verilog (the language) is way more clever than that. It does not merely &amp;quot;compile&amp;quot; the design, but &lt;em&gt;synthesize&lt;/em&gt; it. It can infer which blocks to use, depending on logical syntax. Noone would ever write a module such as the one above. Instead, one would simply write the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module and_gate (
    input logic in_0,
    input logic in_1,
    output logic out
);

    assign out = in_0 &amp;amp; in_1;

endmodule
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The tools would determine that you are assigning &lt;code&gt;out&lt;/code&gt; to be the logical &lt;code&gt;AND&lt;/code&gt; between &lt;code&gt;in_0&lt;/code&gt; and &lt;code&gt;in_1&lt;/code&gt;, and that the most convenient block to achieve this is a LUT2. It could as well understand that you want to add two 8-bit numbers, and select and wire together the relevant blocks: a large combination of LUTs maybe, unless the FPGA provides some built-in adder blocks.&lt;/p&gt;
&lt;p&gt;In fact, most designs only explicitly instantiate complex blocks (clocks, memories...) but usually let the language deal with the rest (LUTs, flip-flops...).&lt;/p&gt;
&lt;h4&gt;The Obligatory LED Blinker&lt;/h4&gt;
&lt;p&gt;The following module accepts a clock logic signal as an input, produces a LED logic signal as an output, and would toggle that LED signal periodically, thus blinking the LED.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;module testbench (
    input  logic clk,   // the logical input clock signal
    output logic led    // the logical output signal controlling the LED
);
    localparam COUNT_WIDTH = 8;

    // count and next_count are a multiple-bits signals of width COUNT_WIDTH
    var logic [COUNT_WIDTH-1:0] count, next_count;

    initial count = 0;

    // the next_count signal continuously updates to be count + 1
    // it's only bits: when count reaches its max value, it wraps to zero
    assign next_count = count + 1;

    // the led signal continuously reflects the highest bit of the count signal
    assign led = count[COUNT_WIDTH-1];

    // on each raising edge of the clk signal,
    // update the count signal with its next value
    always @ (posedge clk) count &amp;lt;= next_count;

endmodule
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Things defined as &lt;code&gt;var&lt;/code&gt; are internal signals, similar to a wire connecting blocks. &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;assign&lt;/code&gt; statement means: the signal on the left-hand side of the &lt;code&gt;=&lt;/code&gt; sign should constantly reflect the result of the expression on the right-hand site. They would probably be implemented with LUTs.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;always @ (posedge clk)&lt;/code&gt; means: the signals on the left-hand side of the &lt;code&gt;&amp;lt;=&lt;/code&gt; signs should be updated to reflect the result of the expressions on the right-hand sign, on each raising edge of the &lt;code&gt;clk&lt;/code&gt; signal. They would probably be implemented with a combination of LUTs and flip-flops.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; is an array of bits, containing &lt;code&gt;COUNT_WIDTH&lt;/code&gt; bits. It is constantly incremented. If &lt;code&gt;COUNT_WITH&lt;/code&gt; is 2, then &lt;code&gt;count&lt;/code&gt; would be &lt;code&gt;00&lt;/code&gt;, &lt;code&gt;01&lt;/code&gt;, &lt;code&gt;10&lt;/code&gt;, &lt;code&gt;11&lt;/code&gt;, &lt;code&gt;00&lt;/code&gt;, &lt;code&gt;01&lt;/code&gt;, etc. and its highest bit would be 0 half of the time, and 1 the other half.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Assuming you tell Vivado to wire the &lt;code&gt;clk&lt;/code&gt; input to the on-board physical clock, and the &lt;code&gt;led&lt;/code&gt; output to a LED, and if you configure &lt;code&gt;COUNT_WIDTH&lt;/code&gt; correctly as per the &lt;code&gt;clk&lt;/code&gt; signal frequency... this should blink the LED on the board.&lt;/p&gt;
&lt;h4&gt;Or Maybe Not&lt;/h4&gt;
&lt;p&gt;And then what? There is no way you can plug a debugger into the FPGA. Remember, there is no &amp;quot;code&amp;quot; executing: everything is happening at hardware, electrical level, and you cannot inspect what happens at silicon level. For very large designs, Xilinx &lt;em&gt;does&lt;/em&gt; provide some methods to add analysis features to your design and actually extract the value of some signals, but they are rather cumbersome and intrusive.&lt;/p&gt;
&lt;p&gt;It is all a black box.&lt;/p&gt;
&lt;p&gt;All you can do is go back to your design, and think.&lt;/p&gt;
&lt;p&gt;On the other hand, FPGA tools such as the Vivado IDE can &lt;em&gt;simulate&lt;/em&gt; a design, i.e. emulate the complete behavior of the elements, all within the PC memory. Vivado comes with a virtual logic analyzer, which shows the signals in details. Here is an example of waveforms it can produce.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/5fujw43s/led-wave-2-mw-600.png?hmac=666ec7bde8547b15e7a84ccb52c6c445e94e255212ee0d7e4cb0d3c234badaf8" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Such an analysis will help you figure out your logical errors, to the point that the simulation is correct. And then... If the code does not have syntax errors, and the design simulates correctly, everything should run successfully on hardware too.&lt;/p&gt;
&lt;p&gt;Let us stop on that (naïvely?) positive note here. &lt;/p&gt;
&lt;p&gt;To be continued!&lt;/p&gt;
</description>
      <pubDate>Mon, 25 Jul 2022 19:00:00 Z</pubDate>
      <a10:updated>2022-07-25T19:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">11315</guid>
      <link>http://www.zpqrtbnk.net/posts/iasyncdisposable-pitfalls/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>IAsyncDisposable Pitfalls</title>
      <description>&lt;p&gt;The .NET ecosystem comes with more and more sophisticated Roslyn Analyzers which &lt;em&gt;may&lt;/em&gt; seem annoying but actually are quite useful at improving our code and detecting hidden and tricky issues.&lt;/p&gt;
&lt;p&gt;Say we have a &lt;code&gt;Method&lt;/code&gt; method that uses a &lt;code&gt;thing&lt;/code&gt; object, which implements &lt;code&gt;IAsyncDisposable&lt;/code&gt; and is produced by an async &lt;code&gt;GetAsyncDisposableAsync&lt;/code&gt; method. We know about the &lt;code&gt;await using&lt;/code&gt; pattern, which guarantees that the object will be async-disposed when the method exits. We have learned that we need to use &lt;code&gt;ConfigureAwait&lt;/code&gt; on awaited tasks (else, we get the &lt;a href="https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2007"&gt;CA2007: Do not directly await a Task&lt;/a&gt; warning). And so, we write the following code:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task Method()
{
    await using var thing = await GetAsyncDisposableAsync().ConfigureAwait(false);

    // use the thing
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is a bit convoluted, but does what we want.&lt;/p&gt;
&lt;h4&gt;Or, does it?&lt;/h4&gt;
&lt;p&gt;Recently, This code started to produce the &lt;a href="https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2007"&gt;CA2007: Do not directly await a Task&lt;/a&gt; warning) &lt;em&gt;again&lt;/em&gt;. Despite the fact that we are, well, obviously &lt;em&gt;not&lt;/em&gt; directly awaiting the task.&lt;/p&gt;
&lt;p&gt;Or... which task? It turns out that there are &lt;em&gt;two&lt;/em&gt; tasks at stake here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When we obtain the &lt;code&gt;thing&lt;/code&gt; object, we run the async &lt;code&gt;GetAsyncDisposable&lt;/code&gt; method, which returns a &lt;code&gt;Task&amp;lt;IAsyncDisposable&amp;gt;&lt;/code&gt;, which we await immediately&lt;/li&gt;
&lt;li&gt;When the &lt;code&gt;await using&lt;/code&gt; pattern implicitly async-disposes the object at the end of the method, it runs the async &lt;code&gt;thing.DisposeAsync&lt;/code&gt; method, which returns a &lt;code&gt;ValueTask&lt;/code&gt;, which is awaited&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we write the following code, where &lt;code&gt;GetAsyncDisposable&lt;/code&gt; is synchronous, the compiler will &lt;em&gt;reuse&lt;/em&gt; the &lt;code&gt;ConfigureAwait&lt;/code&gt; statement when awaiting the &lt;code&gt;DisposeAsync&lt;/code&gt; task.&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;await using var y = GetAsyncDisposable().ConfigureAwait(false);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, when we write the following code, where &lt;code&gt;GetAsyncDisposable&lt;/code&gt; is asynchronous, the compiler &lt;em&gt;has&lt;/em&gt; to use the &lt;code&gt;ConfigureAwait&lt;/code&gt; statement immediately and is left with no hint about how to await the &lt;code&gt;DisposeAsync&lt;/code&gt; task.&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;await using var y = await GetAsyncDisposableAsync().ConfigureAwait(false);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And, don't think about putting &lt;em&gt;two&lt;/em&gt; &lt;code&gt;ConfigureAwait&lt;/code&gt; statements there, it does not work. There is a &lt;a href="https://github.com/dotnet/csharplang/discussions/2661"&gt;lengthy discussion&lt;/a&gt; about this situation in the C# lang repository, which essentially concludes that there is no pretty way to handle the situation. It's one area where the C# design fails.&lt;/p&gt;
&lt;h4&gt;Solution (sort-of)&lt;/h4&gt;
&lt;p&gt;The solution idea is to separate the &lt;code&gt;await using&lt;/code&gt; statement from the retrieval of the &lt;code&gt;IAsyncDisposable&lt;/code&gt; object. In other words: don't &lt;code&gt;await using&lt;/code&gt; something that is obtained asynchronously. Our code can become:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task Method()
{
    var thing = await GetAsyncDisposableAsync().ConfigureAwait(false);
    await using (thing.ConfigureAwait(false))
    {
        // use the thing
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now we &lt;em&gt;do&lt;/em&gt; have our two &lt;code&gt;ConfigureAwait&lt;/code&gt; calls, and C# will use the one in the &lt;code&gt;await using&lt;/code&gt; block when awaiting the &lt;code&gt;DisposeAsync&lt;/code&gt; &lt;code&gt;ValueTask&lt;/code&gt;. Note however that we lose the convenient one-line &lt;code&gt;await using&lt;/code&gt; syntax. We can get it back with this other version:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public async Task Method()
{
    var thing = await GetAsyncDisposableAsync().ConfigureAwait(false);
    await using var thingd = thing.ConfigureAwait(false);

    // use the thing
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;a href="https://github.com/dotnet/csharplang/discussions/2661"&gt;discussion&lt;/a&gt; on the C# repository proposes even more esoteric solutions and some weird-looking extension methods that, in my mind, render things even more confusing. It is an interesting read nevertheless :)&lt;/p&gt;
</description>
      <pubDate>Tue, 19 Jul 2022 13:00:00 Z</pubDate>
      <a10:updated>2022-07-19T13:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">10969</guid>
      <link>http://www.zpqrtbnk.net/posts/the-curse-of-null/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>The Curse of NULL</title>
      <description>&lt;p&gt;C# has two main categories of types: &lt;em&gt;value types&lt;/em&gt; and &lt;em&gt;reference types&lt;/em&gt;. A variable of a value type contains an instance of the type, while a variable of a reference type contains a &lt;em&gt;reference&lt;/em&gt; to an instance of the type. In a very non-technical way, one could say that a value type variable is the &amp;quot;thing&amp;quot; itself, while a reference type variable &lt;em&gt;points&lt;/em&gt; to the &amp;quot;thing&amp;quot;.&lt;/p&gt;
&lt;p&gt;An integer, for instance, is a value type. An integer variable contains the value itself. It has to be a valid integer value (in the &lt;code&gt;int.MinValue&lt;/code&gt; to &lt;code&gt;int.MaxValue&lt;/code&gt; range), and is zero by default. And technically, anything that can fit in a value type (ignoring &lt;code&gt;struct&lt;/code&gt; here) is valid: if an &lt;code&gt;int&lt;/code&gt; is composed of four bytes i.e. 32 bits, any combination of these 32 bits is going to produce a valid &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An object can be a reference type, when it is defined as a &lt;code&gt;class&lt;/code&gt;. A &lt;code&gt;class&lt;/code&gt; object variable contains a &lt;em&gt;reference&lt;/em&gt; to the object, not the object itself. More precisely, it contains a &lt;em&gt;number&lt;/em&gt; (32 bits on 32 bit OS, 64 bits on 64 bits OS) which is the &lt;em&gt;address&lt;/em&gt; of the object in memory.&lt;/p&gt;
&lt;p&gt;A reference type variable &lt;em&gt;has&lt;/em&gt; to point to a valid object of the correct type, and of course not every number point to such an object: some numbers would be &lt;em&gt;invalid&lt;/em&gt;. Luckily C# makes sure that, by default, all reference variables are &lt;em&gt;valid&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Except for one situation.&lt;/p&gt;
&lt;h4&gt;Enters NULL&lt;/h4&gt;
&lt;p&gt;C# allows reference type variables to use the underlying value &lt;em&gt;zero&lt;/em&gt; a.k.a. &lt;code&gt;null&lt;/code&gt;, which is not a valid memory address, to indicate that they actually do &lt;em&gt;not&lt;/em&gt; point to an object. It can be convenient, when you think of it, and the concept is widely used in databases: if the &lt;code&gt;Name&lt;/code&gt; column contains &lt;code&gt;null&lt;/code&gt;, we don't know the name of the person.&lt;/p&gt;
&lt;p&gt;At C# code level however, &lt;code&gt;null&lt;/code&gt; is sort of cursed. And why so? Because... if the variable &lt;code&gt;thing&lt;/code&gt; is of type &lt;code&gt;Thing&lt;/code&gt; which is defined as a &lt;code&gt;class&lt;/code&gt;, and the value of the variable is &lt;code&gt;null&lt;/code&gt;, what is the value of &lt;code&gt;thing.Value&lt;/code&gt;? It cannot be determined, and trying to access it provokes a &lt;code&gt;NullReferenceException&lt;/code&gt; at runtime. Once &lt;code&gt;null&lt;/code&gt; is authorized, programmers have to take great care everywhere to handle, and guard against, &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Oh and, the default value of a reference type variable is &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Nullable Value Type&lt;/h4&gt;
&lt;p&gt;Now imagine that one wants a variable that indicates whether a user is OK with receiving spam, and aso imagine that this variable is meaningless as long as the user has not explicitly indicated whether they are OK with spam or not. Unfortunately, a &lt;code&gt;bool&lt;/code&gt; variable is &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; and nothing else. Of course the proper way do handle this would be via two separate variables:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;bool isOkWithSpam;
bool hasIndicatedSpamPreference;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But, inspired by the &lt;code&gt;null&lt;/code&gt; usage for references, C# introduced the &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; structure which can at the same time carry a value, &lt;em&gt;and&lt;/em&gt; indicate whether it has a value or not. And, to make it even friendlier, it introduced syntactic sugar that would allow one to pretend that the variable could be &lt;code&gt;null&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;bool? isOkWithSpam;    // compiles as: Nullable&amp;lt;bool&amp;gt; isOkWithSpam;
isOkWithSpam = null;   // compiles as: isOkWithSpam.HasValue = false;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that a &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; has &amp;quot;interesting&amp;quot; properties. You probably know already that the C# language can &amp;quot;box&amp;quot; an integer value type into an object. In the code below, the &lt;code&gt;o&lt;/code&gt; variable is of type &lt;code&gt;object&lt;/code&gt; and contains an actual &lt;code&gt;System.Int32&lt;/code&gt; value, obtained at the time of boxing (don't confuse it with a &lt;em&gt;reference to &lt;code&gt;i&lt;/code&gt;&lt;/em&gt;&amp;mdash; such a reference does not exist and changing &lt;code&gt;i&lt;/code&gt; does not change &lt;code&gt;o&lt;/code&gt;):&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;var i = 33;
var o = (object) i;
Console.WriteLine(o.GetType()); // &amp;quot;System.Int32&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now what happens when you box a &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt;? You &lt;em&gt;may&lt;/em&gt; think that you would get a variable of type &lt;code&gt;object&lt;/code&gt; containing an actual &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; value. But actually... boxing unwraps the &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; structure, and what you finally get depends on whether there was a value or not:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;var i = (int?) 33;
var o = (object) i; // o is of type System.Int32
var ni = (int?) null;
var no = (object) ni; // o is null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All in all, the C# language support for nullable values is pretty nice, you can even sum several &lt;code&gt;int?&lt;/code&gt; value and get an actual result if no value is &lt;code&gt;null&lt;/code&gt;, or &lt;code&gt;null&lt;/code&gt; if one value is &lt;code&gt;null&lt;/code&gt;... The language designers looked at nullable value type variables, and thought it was a very good thing.&lt;/p&gt;
&lt;h4&gt;Nullable Reference Type&lt;/h4&gt;
&lt;p&gt;Others found that the whole concept of a variable being &lt;code&gt;null&lt;/code&gt; was very wrong and dangerous. They thought that a &lt;code&gt;string&lt;/code&gt; variable should always contain an actual string, no matter what, maybe the empty string by default, but not never ever &lt;em&gt;nothing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;However, imposing such a change on the CLR would be a &lt;em&gt;massive&lt;/em&gt; breaking change. Actually, an impossible one. So they had this idea: technically, the CLR would still support &lt;code&gt;null&lt;/code&gt; references, but the &lt;em&gt;compiler&lt;/em&gt; would try its best to detect and prevent them. &lt;/p&gt;
&lt;p&gt;When the &lt;code&gt;nullable&lt;/code&gt; feature of the compiler is enabled, a &lt;code&gt;string&lt;/code&gt; variable is assumed to be non-&lt;code&gt;null&lt;/code&gt;. The following code would raise a warning (note: not an error).&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;string s;
s = null; // warning!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And, for consistency purposes, the value type nullable notation has been reused to indicate a reference variable that is authorized to be &lt;code&gt;null&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;string? s;
s = null; // no warning
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Though initially annoying, this can quickly point to errors in code and is in fact quite nice.&lt;/p&gt;
&lt;p&gt;Some caveats: if you write a library that expose a method such as:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public void WriteLength(string s)
{
    Console.WriteLine(s.Length);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler will assume that this is safe, since the variable is of type &lt;code&gt;string&lt;/code&gt;, which indicates it cannot be &lt;code&gt;null&lt;/code&gt;. However, remember that this is a compiler-level check. Nothing prevents a user of your library to disable the nullable checks, and pass &lt;code&gt;null&lt;/code&gt; to your method. Therefore, it is still a good practice to check parameters for &lt;code&gt;null&lt;/code&gt; values in publicly-exposed methods:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public void WriteLength(string s)
{
    if (s == null) throw new ArgumentNullException(nameof(s));
    Console.WriteLine(s.Length);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But for everything internal, it should be safe to trust the compiler.&lt;/p&gt;
&lt;h4&gt;And then it becomes complicated&lt;/h4&gt;
&lt;p&gt;Now imagine a function that may return a value, or may want to indicate that it has no value to return. This is a typical use case for nullable.&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public T? GetValue&amp;lt;T&amp;gt;() { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alas, with C# 8, that would not compile. The problem here is that &lt;code&gt;T?&lt;/code&gt; can mean two very different things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;T&lt;/code&gt; is a value type, &lt;code&gt;T?&lt;/code&gt; is syntactic sugar for &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;If &lt;code&gt;T&lt;/code&gt; is a reference type, &lt;code&gt;T?&lt;/code&gt; is actually &lt;code&gt;T&lt;/code&gt; but with a hint for the compiler to assume that the value can be &lt;code&gt;null&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We end up with a function that can return &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;T&lt;/code&gt;, which is an impossible situation. One has to &lt;em&gt;constrain&lt;/em&gt; &lt;code&gt;T&lt;/code&gt; for the code to compile:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public T? GetValValue&amp;lt;T&amp;gt;() where T : struct { ... }
public T? GetRefValue&amp;lt;T&amp;gt;() where T : class { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C# 9 has a better support for nullable, and does compile the following function:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public T? GetValue&amp;lt;T&amp;gt;() { return default; }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, can you guess the output of the following code:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;Console.WriteLine(GetValue&amp;lt;string&amp;gt;());
Console.WriteLine(GetValue&amp;lt;int&amp;gt;());
Console.WriteLine(GetValue&amp;lt;int?&amp;gt;());
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The first line outputs nothing, which makes sense: &lt;code&gt;GetValue&amp;lt;string&amp;gt;&lt;/code&gt; returns a &lt;code&gt;string?&lt;/code&gt; value, which really at IL code / CLR level is a &lt;code&gt;string&lt;/code&gt;, and the default value is &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second line outputs... zero. How come? The reason is, even in version 9 C# cannot do miracle and return both &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt;. The method is being called with &lt;code&gt;T&lt;/code&gt; being &lt;code&gt;int&lt;/code&gt;, so it returns &lt;code&gt;default(int)&lt;/code&gt; i.e. zero, as &lt;code&gt;T&lt;/code&gt;. So, even though the code now compiles, it does not exactly produces what we would expect (&lt;code&gt;null&lt;/code&gt;). In fact, the method &lt;em&gt;cannot&lt;/em&gt; return a &lt;code&gt;null&lt;/code&gt; value type.&lt;/p&gt;
&lt;p&gt;The third line outputs nothing. &lt;code&gt;GetValue&amp;lt;int?&amp;gt;&lt;/code&gt; returns a... &lt;code&gt;int??&lt;/code&gt; value, I guess, which really is a &lt;code&gt;int?&lt;/code&gt; with the second &lt;code&gt;?&lt;/code&gt; being discarded because &lt;code&gt;int?&lt;/code&gt; is a value type. But in this case, the method is being called with &lt;code&gt;T&lt;/code&gt; being &lt;code&gt;int?&lt;/code&gt;, so it returns &lt;code&gt;default(int?)&lt;/code&gt; i.e. &lt;code&gt;null&lt;/code&gt;, as &lt;code&gt;T&lt;/code&gt; (again), which happens to be &lt;code&gt;int?&lt;/code&gt;, so we get a &lt;code&gt;null&lt;/code&gt; value type. Are you still with me?&lt;/p&gt;
&lt;h4&gt;So what?&lt;/h4&gt;
&lt;p&gt;In &lt;em&gt;most cases&lt;/em&gt; you will ignore all this and happily use nullable values here and there without issues. Just remember that nullable values and &lt;code&gt;null&lt;/code&gt; references, though sharing a very similar syntax, are not exactly the same thing. And, come back and read again this post the day you will get this very odd behavior that you do not quite understand!&lt;/p&gt;
</description>
      <pubDate>Fri, 10 Jun 2022 19:35:00 Z</pubDate>
      <a10:updated>2022-06-10T19:35:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">5702</guid>
      <link>http://www.zpqrtbnk.net/posts/csharp-fixme-code-comments/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <category>dotnet</category>
      <title>CSharp FIXME Code Comments</title>
      <description>&lt;p&gt;When working on code, I sometime can get deep in &amp;quot;the zone&amp;quot;, a creative state where ideas keep flowing and I start refactoring things all around the code base, making quick and dirty changes here and there just to be able to go where I know I want to go. This is accumulating technical debt, and as with any debt, I believe that it can be a good thing, as long as it lets me achieve my goal &lt;em&gt;and&lt;/em&gt; there is a reliable plan to repay that debt eventually.&lt;/p&gt;
&lt;p&gt;Part of that process requires that that debt can be made highly visible. I love to drop &amp;quot;FIXME comments&amp;quot; in my code for that purpose. &lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public void MyMethod()
{
    // get a value and use it
    // FIXME this may throw and then we should handle it
    var s = GetSomething();
    
    UseTheValue(s);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ReSharper is nice enough to color these comments, and tag them in the scrollbar.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/2k3dskqy/shot1.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;ReSharper also provides a useful &lt;em&gt;To-to explorer&lt;/em&gt; which provides an overview of all these comments, with a way to easily navigate to each of them.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/r3ihxnj2/shot2.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;However... dealing with these FIXMEs remain a proactive and somewhat tedious task, and it is quite easy to forget about it, especially if one is prone to procrastination... leading to inevitable debt accumulation.&lt;/p&gt;
&lt;h4&gt;Show me FIXMEs&lt;/h4&gt;
&lt;p&gt;I am trying to address this situation via Roslyn &lt;a href="https://docs.microsoft.com/en-us/visualstudio/code-quality/roslyn-analyzers-overview"&gt;Code Analysis&lt;/a&gt;. I have created a &lt;em&gt;Comments Build Analyzer&lt;/em&gt; (available on &lt;a href="https://www.nuget.org/packages/ZpqrtBnk.CommentsBuildAnalyzer/"&gt;NuGet&lt;/a&gt; with source code on &lt;a href="https://github.com/zpqrtbnk/comments-build-analyzer"&gt;GitHub&lt;/a&gt;) which detects FIXME comments, and creates corresponding warnings that show in the &lt;em&gt;Error List&lt;/em&gt; pane.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/fs4itkwr/shot3.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;At the moment, &lt;code&gt;FIXME&lt;/code&gt; comment are reported with code &lt;code&gt;ZB1001&lt;/code&gt; and &lt;code&gt;FIXME!&lt;/code&gt; (note the bang) comments are reported with code &lt;code&gt;ZB1002&lt;/code&gt;. All you have to do is install the NuGet package in your project.&lt;/p&gt;
&lt;p&gt;Combine this with &lt;code&gt;.editorconfig&lt;/code&gt; files, and it becomes even more (painful?) useful. It is possible to use configuration-dependent &lt;code&gt;.editorconfig&lt;/code&gt; files by registering them in the &lt;code&gt;.csproj&lt;/code&gt; file.&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;&amp;lt;ItemGroup Condition=&amp;quot;'$(Configuration)'=='Debug'&amp;quot;&amp;gt;
    &amp;lt;EditorConfigFiles Include=&amp;quot;debug.editorconfig&amp;quot; Link=&amp;quot;.editorconfig&amp;quot;/&amp;gt;
&amp;lt;/ItemGroup&amp;gt;

&amp;lt;ItemGroup Condition=&amp;quot;'$(Configuration)'=='Release'&amp;quot;&amp;gt;
      &amp;lt;EditorConfigFiles Include=&amp;quot;release.editorconfig&amp;quot; Link=&amp;quot;.editorconfig&amp;quot;/&amp;gt;
&amp;lt;/ItemGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, if &lt;code&gt;debug.editorconfig&lt;/code&gt; contains:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;dotnet_diagnostic.ZB1002.severity = warning # FIXME!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;While &lt;code&gt;release.editorconfig&lt;/code&gt; contains:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;dotnet_diagnostic.ZB1002.severity = error # FIXME!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;FIXME!&lt;/code&gt; comments will raise warnings in the &lt;code&gt;Debug&lt;/code&gt; build (so they will not prevent you from developing and building and testing, as &lt;code&gt;#error&lt;/code&gt; statements would), and will raise &lt;em&gt;errors&lt;/em&gt; in the &lt;code&gt;Release&lt;/code&gt; build&amp;mdash;and thus fail it.&lt;/p&gt;
&lt;p&gt;The end result being that, with a properly configured CI, the build would break in case you ever leak a &lt;code&gt;FIXME!&lt;/code&gt; comment. I still need to use it for some time and evaluate whether this is &lt;em&gt;really&lt;/em&gt; useful,or just fancy, but so far it makes me feel safer.&lt;/p&gt;
</description>
      <pubDate>Tue, 16 Mar 2021 09:20:00 Z</pubDate>
      <a10:updated>2021-03-16T09:20:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">3946</guid>
      <link>http://www.zpqrtbnk.net/posts/optimizing-csharp-null-coalescing-operator/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>Optimizing CSharp Null-Coalescing Operator</title>
      <description>&lt;p&gt;Consider the following code:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public Func&amp;lt;int&amp;gt; F { get; set; }

private int GetValue()
{
    // return the value produced by F, 
    // if F is not null, else zero
} 
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I naïvely implemented the function as:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;if (F == null) return default;
return F();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Does the job.&lt;/p&gt;
&lt;h4&gt;Elegant Code&lt;/h4&gt;
&lt;p&gt;Yet, ReSharper squiggled the &lt;code&gt;if&lt;/code&gt; statement, suggesting I might want to convert to:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;return F == null ? default : F();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which is nice indeed. Ah, ReSharper now squiggles the &lt;code&gt;== null&lt;/code&gt; statement, suggesting I merge the conditional expression into:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;return F?.Invoke() ?? default;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And... I started to wonder. It certainly is more compact. But is it cleaner?
It reminds me of a &lt;a href="https://twitter.com/FransBouma/status/1326456729102659585"&gt;recent thead&lt;/a&gt; initiated by Frans, on the topic of C# getting more and more syntax-complex, to the point that C++ looks elegant and you need ReSharper to remind you of all the new bells and whistles.&lt;/p&gt;
&lt;p&gt;Thank you, but no. Obfuscation can &lt;a href="https://en.wikipedia.org/wiki/International_Obfuscated_C_Code_Contest"&gt;sure be fun&lt;/a&gt;, but one day I might have to troubleshoot that code, and I do prefer the &lt;code&gt;?:&lt;/code&gt; pattern over the &lt;code&gt;?.Invoke ??&lt;/code&gt; one. As Steve &lt;a href="https://twitter.com/Steve_Gibe/status/1326475063277793280"&gt;replied&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;It's just obfuscating the intent of your code. Clarity over minimal keystrokes. I gotta support this code for years.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(rant) Every developer should have to spend some time doing 24/7 support on production-critical code. Once you have been waken up at 3am to spend hours trying to figure out what is wrong with some recent code changes while the entire factory waits for you to restart operations... you get a different idea of what elegant code is. (/rant)&lt;/p&gt;
&lt;p&gt;Anyways.&lt;/p&gt;
&lt;h4&gt;And besides, it is not the same!&lt;/h4&gt;
&lt;p&gt;At that point I got a carried on by my rant, and started to think:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With the &lt;code&gt;?.&lt;/code&gt; pattern, if the function is &lt;code&gt;null&lt;/code&gt;, we return the &lt;em&gt;value type&lt;/em&gt; default value, else execute the function and return the &lt;em&gt;value type&lt;/em&gt; result&lt;/li&gt;
&lt;li&gt;With the &lt;code&gt;?.Invoke ??&lt;/code&gt; pattern, if the function is &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;?.Invoke&lt;/code&gt; will be &lt;code&gt;null&lt;/code&gt; i.e. a &lt;em&gt;reference type&lt;/em&gt;, so there has to be some &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing"&gt;boxing and unboxing&lt;/a&gt; happening under the hood for the &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator"&gt;?? operator&lt;/a&gt; to work&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And so, the &lt;code&gt;?.Invoke ??&lt;/code&gt; pattern has to be worse, performance-wise!&lt;/p&gt;
&lt;p&gt;Time to turn to &lt;a href="https://sharplab.io/"&gt;Sharplab.io&lt;/a&gt;. This amazing tool let you type C# code on the left, and presents you with the resulting IL or assembly code on the right:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/lihjtmd4/2020-11-21-09_50_12-sharplab-io-sharplab-mw-600.png?hmac=5b5e5b40754ec3b2721001965a7203ae5fb0117e0b89a09a2a05a345b4010fda" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;We are going to compile the following code:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public Func&amp;lt;int&amp;gt; F { get; set; }
    
public int M1() 
{
    return F == null
        ? 0
        : F();
}
    
public int M2() 
{
    return F?.Invoke() ?? 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For &lt;code&gt;M1&lt;/code&gt; the IL code (in Release mode) is:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;IL_0000: ldarg.0
IL_0001: call instance class [System.Private.CoreLib]System.Func`1&amp;lt;int32&amp;gt; C::get_F()
IL_0006: brfalse.s IL_0014

IL_0008: ldarg.0
IL_0009: call instance class [System.Private.CoreLib]System.Func`1&amp;lt;int32&amp;gt; C::get_F()
IL_000e: callvirt instance !0 class [System.Private.CoreLib]System.Func`1&amp;lt;int32&amp;gt;::Invoke()
IL_0013: ret

IL_0014: ldc.i4.0
IL_0015: ret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And for &lt;code&gt;M2&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;IL_0000: ldarg.0
IL_0001: call instance class [System.Private.CoreLib]System.Func`1&amp;lt;int32&amp;gt; C::get_F()
IL_0006: dup
IL_0007: brtrue.s IL_000c

IL_0009: pop
IL_000a: ldc.i4.0
IL_000b: ret

IL_000c: callvirt instance !0 class [System.Private.CoreLib]System.Func`1&amp;lt;int32&amp;gt;::Invoke()
IL_0011: ret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;First, note that the &lt;code&gt;?.&lt;/code&gt; coalesce operator does &lt;em&gt;not&lt;/em&gt; imply any kind of boxing, as I originally thought. So it &lt;em&gt;is&lt;/em&gt; safe. In fact, the code produced for &lt;code&gt;M2&lt;/code&gt; looks simpler, especially with &lt;code&gt;M1&lt;/code&gt; invoking &lt;code&gt;get_F()&lt;/code&gt; &lt;em&gt;twice&lt;/em&gt; in case &lt;code&gt;F&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt;. However, remember this is only IL code. There is another level of optimization in the JIT, which leads to the following x86 assembly code:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;C.M1()
    L0000: mov eax, [ecx+4]
    L0003: test eax, eax
    L0005: je short L000e
    L0007: mov ecx, [eax+4]
    L000a: call dword ptr [eax+0xc]
    L000d: ret
    L000e: xor eax, eax
    L0010: ret

C.M2()
    L0000: mov edx, [ecx+4]
    L0003: test edx, edx
    L0005: jne short L000a
    L0007: xor eax, eax
    L0009: ret
    L000a: mov ecx, [edx+4]
    L000d: call dword ptr [edx+0xc]
    L0010: ret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In other words, both methods end up doing &lt;em&gt;almost&lt;/em&gt; exactly the same, at assembly level. And benchmarks (see below, if you &lt;em&gt;really&lt;/em&gt; are into this) show that they perform the same. This is a good thing: it means that one can use one syntax or the other, without worrying about performance.&lt;/p&gt;
&lt;p&gt;As for code elegance, I know what I prefer.&lt;/p&gt;
&lt;h4&gt;Appendix&lt;/h4&gt;
&lt;p&gt;This is more details, for people who are into it.&lt;/p&gt;
&lt;p&gt;Just to be sure, I have benchmarked the two methods. The BenchmarkDotNet code is quite simple (see &lt;a href="https://gist.github.com/zpqrtbnk/490025ea4b720ba2f06ae827c88f18ee"&gt;this Gist&lt;/a&gt;) and I have executed it with &lt;code&gt;F&lt;/code&gt; being &lt;code&gt;null&lt;/code&gt;, or returning a constant, or computing a value... and, funny enough, I never get the exact same duration for both methods, and one or the other is always randomly slightly faster that the other. I guess that is due to glitches on my benchmark machine, and it means that the methods are equivalent.&lt;/p&gt;
&lt;p&gt;Just to be &lt;em&gt;super sure&lt;/em&gt;, I fired WinDBG at the benchmark, after it had run. First you want to locate the class:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;&amp;gt; !name2ee Benchmarks!Benchmarks.NullCoalesce
Module:      00007ff98a5cf800
Assembly:    Benchmarks.dll
Token:       0000000002000005
MethodTable: 00007ff98a69ea80
EEClass:     00007ff98a689038
Name:        Benchmarks.NullCoalesce
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then you want to dump the method table:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;&amp;gt; !dumpmt -md 00007ff98a69ea80
EEClass:         00007ff98a689038
Module:          00007ff98a5cf800
Name:            Benchmarks.NullCoalesce
mdToken:         0000000002000005
File:            D:\d\Benchmarks\bin\Release\netcoreapp3.1\Benchmarks.dll
BaseSize:        0x20
ComponentSize:   0x0
Slots in VTable: 11
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
           Entry       MethodDesc    JIT Name
00007FF98A520090 00007ff98a4f0a80   NONE System.Object.Finalize()
00007FF98A520098 00007ff98a4f0a90   NONE System.Object.ToString()
00007FF98A5200A0 00007ff98a4f0aa0    JIT System.Object.Equals(System.Object)
00007FF98A5200B8 00007ff98a4f0ae0    JIT System.Object.GetHashCode()
00007FF98A538F30 00007ff98a69e9f8   NONE Hazelcast.Benchmarks.NullCoalesce..ctor()
00007FF98A538F20 00007ff98a69e9c8    JIT Benchmarks.NullCoalesce.get_F()
00007FF98A538F28 00007ff98a69e9e0   NONE Benchmarks.NullCoalesce.set_F(System.Func`1)
00007FF98A538F38 00007ff98a69ea08    JIT Benchmarks.NullCoalesce.BenchmarkM1()
00007FF98A538F40 00007ff98a69ea20    JIT Benchmarks.NullCoalesce.M1()
00007FF98A538F48 00007ff98a69ea38    JIT Benchmarks.NullCoalesce.BenchmarkM2()
00007FF98A538F50 00007ff98a69ea50    JIT Benchmarks.NullCoalesce.M2()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And... &lt;code&gt;!dumpil&lt;/code&gt; can show us the IL code, but we really want the assembly code:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;&amp;gt; !u 00007ff98a69ea20
Normal JIT generated code
Benchmarks.NullCoalesce.M1()
Begin 00007FF98AAB5F20, size 17
00007ff9`8aab5f20 488b4108        mov     rax,qword ptr [rcx+8]
00007ff9`8aab5f24 4885c0          test    rax,rax
00007ff9`8aab5f27 740b            je      00007ff9`8aab5f34
00007ff9`8aab5f29 488b4808        mov     rcx,qword ptr [rax+8]
00007ff9`8aab5f2d 488b4018        mov     rax,qword ptr [rax+18h]
00007ff9`8aab5f31 48ffe0          jmp     rax
00007ff9`8aab5f34 33c0            xor     eax,eax
00007ff9`8aab5f36 c3              ret

&amp;gt; !u 00007ff98a69ea50  
Normal JIT generated code
Benchmarks.NullCoalesce.M2()
Begin 00007FF98AAE4220, size 17
00007ff9`8aae4220 488b5108        mov     rdx,qword ptr [rcx+8]
00007ff9`8aae4224 4885d2          test    rdx,rdx
00007ff9`8aae4227 7503            jne     00007ff9`8aae422c
00007ff9`8aae4229 33c0            xor     eax,eax
00007ff9`8aae422b c3              ret
00007ff9`8aae422c 488b4a08        mov     rcx,qword ptr [rdx+8]
00007ff9`8aae4230 488b4218        mov     rax,qword ptr [rdx+18h]
00007ff9`8aae4234 48ffe0          jmp     rax
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;My .NET host (.NET Core 3.1.9) produces assembly code that is slightly different from what Sharplab.io shows, but the conclusion stands: both methods are, practically, equivalent.&lt;/p&gt;
</description>
      <pubDate>Sat, 21 Nov 2020 13:05:00 Z</pubDate>
      <a10:updated>2020-11-21T13:05:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">2087</guid>
      <link>http://www.zpqrtbnk.net/posts/optimizing-csharp-value-types/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <title>Optimizing CSharp Value Types</title>
      <description>&lt;p&gt;In a Twitter exchange with my friend James, we recently wondered how to properly document methods that return named value tuples. Why would we have to deal with methods returning value tuples? Well, consider this classic method:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public bool TryGetValue(TKey key, out TValue value) { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Enters &lt;code&gt;async&lt;/code&gt;. Ideally, we want:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public async ValueTask&amp;lt;bool&amp;gt; TryGetValue(TKey key, out TValue value) { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But... &lt;code&gt;async&lt;/code&gt; does support &lt;code&gt;out&lt;/code&gt; parameters. And thus, the method logically becomes:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public async ValueTask&amp;lt;(bool, TValue)&amp;gt; TryGetValue(TKey key) { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which leads us to the original question: how would you document such a method?&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;Tries to get a value.&amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;A key.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt; ???? &amp;lt;/returns&amp;gt;
public async ValueTask&amp;lt;(bool, TValue)&amp;gt; TryGetValue(TKey key) { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The subject is not exactly new as Roslyn issue &lt;a href="https://github.com/dotnet/roslyn/issues/13216"&gt;#13216&lt;/a&gt; or CSharp issue &lt;a href="https://github.com/dotnet/csharplang/issues/145"&gt;#145&lt;/a&gt; already explored more or less convoluted solutions in 2016. And somewhere in these issues, one can read:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;&lt;em&gt;tuples really aren't well suited for public APIs or scenarios where you'd need or want to document them&lt;/em&gt;&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With the recommendation to use a record of some sort to return results. Which quite probably means returning a &lt;code&gt;struct&lt;/code&gt; or even a &lt;code&gt;class&lt;/code&gt;... and this is obviously going to cause some allocations, overhead etc.&lt;/p&gt;
&lt;p&gt;Let us say, for the sake of the argument, that we refactor the method as:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;Tries to get a value.&amp;lt;/summary&amp;gt;
/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;A key.&amp;lt;/param&amp;gt;
/// &amp;lt;returns&amp;gt;A attempt at getting the value for the specified key.&amp;lt;/returns&amp;gt;
public async ValueTask&amp;lt;Attempt&amp;lt;TValue&amp;gt;&amp;gt; TryGetValue(TKey key) { ... }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With &lt;code&gt;Attempt&amp;lt;T&amp;gt;&lt;/code&gt; defined as:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public struct Attempt&amp;lt;T&amp;gt;
{
    public bool Success { get; set; }
    public T Value { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now, we are going to allocate an instance of &lt;code&gt;Attempt&amp;lt;T&amp;gt;&lt;/code&gt; each time we return, and then use the property getters (i.e. invoke a method) to figure out whether the attempt was successful, and retrieve the value it carries.&lt;/p&gt;
&lt;p&gt;How bad is it? Just to be sure, I have used &lt;a href="https://sharplab.io/"&gt;SharpLab&lt;/a&gt; to show me the generated IL and assembly code for the following methods:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public void InvokeWithTuple()
{
    var (success, value) = TryGetValueWithTuple(&amp;quot;foo&amp;quot;);
    if (success) Console.WriteLine(value);
}

public void InvokeWithAttempt()
{
    var attempt = TryGetValueWithAttempt(&amp;quot;foo&amp;quot;);
    if (attempt.Success) Console.WriteLine(attempt.Value);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is the assembly code generated for the tuple version (in Release mode):&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;L0000: push ebp
L0001: mov ebp, esp
L0003: sub esp, 8
L0006: xor eax, eax
L0008: mov [ebp-8], eax
L000b: mov [ebp-4], eax
L000e: push 1
L0010: lea edx, [ebp-8]
L0013: call C.TryGetValueWithTuple(Boolean)
L0018: mov ecx, [ebp-4]
L001b: movzx ecx, cl
L001e: mov eax, [ebp-8]
L0021: test ecx, ecx
L0023: je short L002c
L0025: mov ecx, eax
L0027: call System.Console.WriteLine(System.String)
L002c: mov esp, ebp
L002e: pop ebp
L002f: ret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now, the assembly code generated for the &lt;code&gt;Attempt&lt;/code&gt; version:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;L0000: push ebp
L0001: mov ebp, esp
L0003: sub esp, 8
L0006: xor eax, eax
L0008: mov [ebp-8], eax
L000b: mov [ebp-4], eax
L000e: push 1
L0010: lea edx, [ebp-8]
L0013: call C.TryGetValueWithAttempt(Boolean)
L0018: cmp byte ptr [ebp-4], 0
L001c: je short L0026
L001e: mov ecx, [ebp-8]
L0021: call System.Console.WriteLine(System.String)
L0026: mov esp, ebp
L0028: pop ebp
L0029: ret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Can you spot the difference? Me neither. But... let us say you are quite fond of the &lt;code&gt;var (success, value) =&lt;/code&gt; syntax. Can we still have it with attempts? Yes, with deconstruction:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;public struct Attempt&amp;lt;T&amp;gt;
{
    public bool Success { get; set; }
    public T Value { get; set; }

    public void Deconstruct(out bool success, out T value)
    {
        success = Success;
        value = Value;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then, this is valid code:&lt;/p&gt;
&lt;pre class="prettyprint"&gt;&lt;code&gt;var (success, value) = TryGetValueWithAttempt(&amp;quot;foo&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But this involves deconstruction... it has to be more expensive, right? I will spare you the assembly code, it is exactly the same. The C# compiler and CLR jitter figure the deconstruction out for you.&lt;/p&gt;
&lt;p&gt;There is one lesson here: the C# compiler and the CLR jitter are quite clever, and you probably want to understand how they work before implementing pointless optimizations. When in doubt, just write clean code.&lt;/p&gt;
</description>
      <pubDate>Wed, 10 Jun 2020 16:00:00 Z</pubDate>
      <a10:updated>2020-06-10T16:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1306</guid>
      <link>http://www.zpqrtbnk.net/posts/what-becomes-of-models-builder/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <title>What Becomes Of Models Builder</title>
      <description>&lt;p&gt;Models Builder is an Umbraco extension that generates C# strongly-typed class models for Umbraco content item.  It allows developers to write &lt;code&gt;@Model.Title&lt;/code&gt; in views instead of the more verbose &lt;code&gt;@Model.Value&amp;lt;string&amp;gt;(&amp;quot;title&amp;quot;)&lt;/code&gt;. Models can be enriched and tweaked to greatly simplify the developement of sites.&lt;/p&gt;
&lt;p&gt;It was originally created in 2013 by me, Stephan, and distributed as an independent NuGet package named &amp;quot;Zbu.ModelsBuilder&amp;quot;. Then, around 2016, it was considered sufficiently important to be bundled with the Umbraco CMS official distribution. On that occasion, it was renamed &amp;quot;Umbraco.ModelsBuilder&amp;quot;. I kept maintaining it as part of my HQ activity.&lt;/p&gt;
&lt;p&gt;When I left HQ in 2019, I proposed to donate the project to HQ, but for various reasons that did not happen. Instead, HQ embedded a simplified version of Models Builder straight into Core&amp;mdash;the one that currently ships with 8.x.&lt;/p&gt;
&lt;p&gt;I, on the other hand, planned to grow and maintain the complete version, as &amp;quot;ZpqrtBnk.ModelsBuilder&amp;quot;, and release long overdue features and fixes. I &lt;em&gt;did&lt;/em&gt; start some work... and then got involved in other non-Umbraco projects, and lost both time and motivation. And then, nothing happened.&lt;/p&gt;
&lt;h4&gt;Models Builder Reloaded&lt;/h4&gt;
&lt;p&gt;Some people grew concerned that one tool they depend on would go abandoned. They reached out to me to discuss the future of Models Builder. It took me a bit of time to digest and accept that, despite all my good intentions, I was not able to do much... but here we are. It is about time to do something.&lt;/p&gt;
&lt;p&gt;As of today, &lt;strong&gt;I am officially donating the project to the Umbraco Community&lt;/strong&gt;. The project is now named &amp;quot;&lt;strong&gt;Our.ModelsBuilder&lt;/strong&gt;&amp;quot;. Its repository has moved to &lt;a href="https://github.com/OurModelsBuilder/Our.ModelsBuilder"&gt;Our.ModelsBuilder&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;h4&gt;Models Builder Team&lt;/h4&gt;
&lt;p&gt;And how exactly is this different from abandonning the project? Well, the general idea is to form a team of maintainers so that the project does not depend on one single person. We need people to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand how it all works and manage the product&lt;/li&gt;
&lt;li&gt;Code&lt;/li&gt;
&lt;li&gt;Maintain the documentation&lt;/li&gt;
&lt;li&gt;Manage the release process, etc&lt;/li&gt;
&lt;li&gt;(probably more?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The good news is that, despite what people like to think, the project is not horribly complex rocket-science. It may require a bit of time to grasp, but then it is rather simple. It is essentially C# with very little UI. This, and I will happily join the team and make myself available to transfer whatever knowledge is required, and answer questions.&lt;/p&gt;
&lt;p&gt;And thus, this is an &lt;strong&gt;official call for members&lt;/strong&gt;. The temporay team is currently composed of myself, &lt;a href="https://twitter.com/franscdejong"&gt;Frans de Jong&lt;/a&gt; and &lt;a href="https://twitter.com/dawoe21"&gt;Dave Woestenborghs&lt;/a&gt;, and we obviously need more people.&lt;/p&gt;
&lt;p&gt;This is a &lt;strong&gt;unique chance&lt;/strong&gt; to have an impact on &lt;strong&gt;one of the most-used Umbraco tool&lt;/strong&gt;. A &lt;strong&gt;unique opportunity&lt;/strong&gt; that you &lt;strong&gt;certainly do not want to miss&lt;/strong&gt;. Of course &lt;strong&gt;you are interested&lt;/strong&gt;, so please contact one of us &lt;strong&gt;now&lt;/strong&gt;, either in the comments of this post, or on the Community Slack, or on Twitter, or by email at &lt;a href="m&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#116;&amp;#x6f;:o&amp;#117;&amp;#114;&amp;#x2e;&amp;#x6d;o&amp;#x64;&amp;#101;&amp;#x6c;sb&amp;#x75;&amp;#x69;&amp;#108;&amp;#x64;&amp;#x65;&amp;#114;&amp;#64;&amp;#x67;m&amp;#97;&amp;#105;&amp;#x6c;&amp;#46;&amp;#99;&amp;#111;&amp;#109;"&gt;&amp;#x6f;&amp;#x75;&amp;#x72;&amp;#46;&amp;#x6d;&amp;#111;&amp;#100;&amp;#101;&amp;#108;&amp;#115;&amp;#98;&amp;#117;&amp;#x69;l&amp;#x64;&amp;#x65;r&amp;#x40;&amp;#103;&amp;#x6d;&amp;#x61;&amp;#105;&amp;#x6c;&amp;#46;&amp;#99;&amp;#x6f;&amp;#x6d;&lt;/a&gt; or by whatever means you feel adequate.&lt;/p&gt;
&lt;p&gt;Do not waste time, &lt;strong&gt;the application closes on the 5th of May, at 05:05am&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Talk to you soon!&lt;/p&gt;
</description>
      <pubDate>Wed, 15 Apr 2020 14:55:00 Z</pubDate>
      <a10:updated>2020-04-15T14:55:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1299</guid>
      <link>http://www.zpqrtbnk.net/posts/three-fives-kit-pcb-edition/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>Three Fives Kit PCB Edition</title>
      <description>&lt;p&gt;Some time ago I &lt;a href="http://www.zpqrtbnk.net/posts/three-fives-kit/" title="Three Fives Kit"&gt;built a Three Fives Kit&lt;/a&gt; from Evil Mad Scientist, and a quick circuit which blinked one LED with a real NE555 timer, and one with the kit.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/1042/img_7114-mw-600.jpg?hmac=f45230a32f31fa0b953899a03ed84c9f946ddcc52385758a772cfb76822340d0" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;This has been sitting on some shelve in my office ever since, but I have always wondered whether I could clean things up a little... maybe building a PCB for the circuit.&lt;/p&gt;
&lt;p&gt;So, I asked on Twitter what people would use to design PCBs, and the always helpful and super-friendly maker Matt Brailsford from &lt;a href="https://circuitbeard.co.uk/"&gt;CircuitBeard&lt;/a&gt; suggested I tried &lt;a href="https://www.kicad-pcb.org/"&gt;KiCad&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Downloading and installing KiCab is relatively easy, but then I quickly hit a steep learning curve. I started reading tutorials... but was, to be honest, going nowhere. And then I found the &lt;a href="https://www.youtube.com/watch?v=BVhWh3AsXQs&amp;amp;list=PLy2022BX6EspFAKBCgRuEuzapuz_4aJCn"&gt;Getting To Blinky 5.0&lt;/a&gt; set of videos by Chris Gammel from &lt;a href="https://contextualelectronics.com/"&gt;Contextual Electronics&lt;/a&gt;. To make it short, these dense videos have &lt;em&gt;everything&lt;/em&gt; you need, in amazing details.&lt;/p&gt;
&lt;p&gt;I will not, therefore, explain KiCad here. Watch the videos. Let's just say that you will end up with a schema:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/teihxrxn/kicad-schema-mw-600.png?hmac=a3e36ac551e9acbfcd54342cf98b393c9e66d8b8d22b94c0f210d9db817fc7f0" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;The schema has two blocks, each blinking a LED with a 555. There is a switch that can be used to select which capacitor to use, to produce either a 500Hz signal (that can be observed with a scope) or a .5Hz signal (to see the LED blink).&lt;/p&gt;
&lt;p&gt;A bit more work takes you to the PCB design itself:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/px0petbt/kicad-pcb-mw-600.png?hmac=9a32154a5c57d5e6b87ef7d7445a9d558f9ec5ebebc55caf62ce0a6960d86216" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;The top copper zones should make it easy to clamp the scope's crocodile plugs to observe signals, while the 555 areas will welcome chip sockets, allowing one to either plug a real 555, or the Three Fives Kit.&lt;/p&gt;
&lt;p&gt;Next, the PCB needs to be manufactured. The recommendation was to go with &lt;a href="https://oshpark.com/"&gt;OshPark&lt;/a&gt; which seems to have fewer options than, say, &lt;a href="https://jlcpcb.com/"&gt;Jlc PCB&lt;/a&gt; or &lt;a href="https://www.pcbway.com/"&gt;PCB Way&lt;/a&gt;&amp;mdash; but that probably is a good thing as I could not understand most of these options anyways.&lt;/p&gt;
&lt;p&gt;Delivery takes a bit of time, because the PCBs are manufactured by batches, but I eventually received this:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/0pwbawtq/img_0668-mw-600.jpg?hmac=c2b2262ec1535821de1380930e9328c31570c1c54bfbfa355ffef21151970963" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Finally, a bit of soldering takes us to the final state. The LED on the left blinks at 500Hz thanks to a true NE555 chip, and can be observed with the scope, while the LED on the right blinks at .5Hz thanks to the Three Five Kits.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/vv0bt1wv/img_0670-mw-600.jpg?hmac=01c5f45b5361e33db5a123182a942d859a464bc7c78bc2639421d9f7b064a2f7" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Looks way cleaner in my office now.&lt;/p&gt;
</description>
      <pubDate>Thu, 19 Mar 2020 17:45:00 Z</pubDate>
      <a10:updated>2020-03-19T17:45:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1294</guid>
      <link>http://www.zpqrtbnk.net/posts/french-developer-keyboard-2/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>French Developer Keyboard (2)</title>
      <description>&lt;p&gt;For years now, my main keyboard has been a black &lt;a href="https://www.daskeyboard.com/"&gt;DasKeyboard&lt;/a&gt;. As in, totally black, no marking. Very much hype. It has allowed me to do cool things, such as remapping the layout to get a &lt;a href=""&gt;French developer keyboard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My layout is a mix of Azerty (French) and Qwerty with characters such as curlies and brackets in convenient places. Makes programming way easier, is easy to learn, and not too different from what everyone uses&amp;mdash;so it's not too hard to switch to and from other machines.&lt;/p&gt;
&lt;p&gt;It always impresses people that I can type without having any marking on the keyboard. The blue Cherry MX switches make an amazingly loud noise... all in all, very cool. At least at the beginning. After a while, typing this very cryptic password without making mistakes reveals tricky, and don't mention the crazy noise.&lt;/p&gt;
&lt;p&gt;In addition, having used my custom layout for about two years now, the positions have stabilized to the following layout, and I don't expect them to move anytime soon.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/cy3a3zqj/layout-mw-600.png?hmac=3f91fb7a166d0bf542922321ca3de21d4d57df818acc39374c22f607f747e851" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;And so... I have finally ordered my own custom &lt;a href="https://www.wasdkeyboards.com/"&gt;WASD&lt;/a&gt; keyboard. It has a very discreet marking, and quiter brown Cherry MX switches.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/0kql4hlm/img_0563-fit-600x240x1x1-0x0x0x0-75.jpg?hmac=58f9ed8f8ad34ae27215b254239e231f85ccdfea2aafdbaab9fdfd5204c24891" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;So far... I'm liking it a lot.&lt;/p&gt;
</description>
      <pubDate>Thu, 12 Mar 2020 14:05:00 Z</pubDate>
      <a10:updated>2020-03-12T14:05:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1292</guid>
      <link>http://www.zpqrtbnk.net/posts/umbraco-life-experiment-feedback/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <category>life</category>
      <title>Umbraco Life Experiment: Feedback</title>
      <description>&lt;p&gt;A few weeks ago I started an &lt;a href="http://www.zpqrtbnk.net/posts/umbraco-life-experiment/" title="Umbraco Life Experiment"&gt;experiment&lt;/a&gt;, and promised to be transparent about it, so... here is some feedback.&lt;/p&gt;
&lt;p&gt;The ZpqrtBnk General License has received a few orders, totalling about 3% of its financing goal. Though other more significant participations have been considered, they will not turn into real orders.&lt;/p&gt;
&lt;h4&gt;What Happened?&lt;/h4&gt;
&lt;p&gt;A broad range of people discussed various topics, such as the value of the General License and what it could deliver, the outcomes of the recent Umbraco &lt;a href="https://umbraco.com/blog/notes-from-the-community-roundtable-discussion/"&gt;Community Roundtable&lt;/a&gt;, how &amp;quot;Umbraco has changed&amp;quot;, the role of a community, and the general direction and agility of the CMS project.&lt;/p&gt;
&lt;p&gt;To make it short, the consensus is that it would probably not be possible to achieve much in the current context. And that it may be time to acknowledge what we cannot change. As a usually discreet community member puts it, it may just be simpler to pretend everything is all right&amp;mdash;and reconsider expectations and commitments.&lt;/p&gt;
&lt;p&gt;The web publishing landscape is quickly evolving, new projects and new ways of building sites appear, new momentums form, safety may require diversification, life is too short, we all want to move forward, all those things.&lt;/p&gt;
&lt;h4&gt;What Does That Take Us?&lt;/h4&gt;
&lt;p&gt;I am now terminating the General License experiment. I will not issue licences, nor invoice anyone.&lt;/p&gt;
&lt;p&gt;To all of you who have encouraged the experiment or raised concerns, offered perspectives, placed or considered orders or explained why you would not: a massive &lt;em&gt;thank you&lt;/em&gt;, #h5yr. I owe you a lot, you truly are a community.&lt;/p&gt;
&lt;p&gt;As far as &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder"&gt;ModelsBuilder&lt;/a&gt; or Umbraco are concerned, I am back to full Open Source mode which, as &lt;a href="https://arstechnica.com/information-technology/2019/10/is-the-software-world-taking-too-much-from-the-open-source-community/"&gt;Bruce Perens states&lt;/a&gt;, is all about generosity&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;. I will happily release new versions and contributions, if and when I have the time and motivation to do so.&lt;/p&gt;
&lt;p&gt;❤︎&lt;/p&gt;
&lt;p&gt;Be seeing U!&lt;/p&gt;

&lt;div class="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Yes, I am considering a Patreon or GitHub sponsorship to help finding time for Models Builder.&amp;nbsp;&lt;a href="#fnref:1" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Tue, 29 Oct 2019 18:35:00 Z</pubDate>
      <a10:updated>2019-10-29T18:35:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1286</guid>
      <link>http://www.zpqrtbnk.net/posts/net-core-30-release/</link>
      <author>sgay@pilotine.com</author>
      <category>dotnet</category>
      <category>umbraco</category>
      <category>beyumbe</category>
      <title>.NET Core 3.0 Release</title>
      <description>&lt;p&gt;This week is &lt;a href="https://www.dotnetconf.net/"&gt;.NET Conf&lt;/a&gt; 2019, and as expected (after a &lt;a href="https://www.theregister.co.uk/2019/09/17/net_core_3_rc1/"&gt;suprise RC1&lt;/a&gt;), .NET Core 3.0 has been officially launched (see the &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0/"&gt;announcement&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;And what better way to celebrate, than to experiment with it?&lt;/p&gt;
&lt;h4&gt;Let the Fun Begin&lt;/h4&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/ioudlvts/netcore-128.png" alt="" class="img-right" /&gt;&lt;/p&gt;
&lt;p&gt;This site now has a B-side, at &lt;a href="http://b.zpqrtbnk.net"&gt;b.zpqrtbnk.net&lt;/a&gt;. It runs on the same Windows server (just another IIS site) and the same database instance. It is, so far, a typical load-balanced scenario. It is powered by Umbraco... on AspNet Core 3.0, thanks to Beyumbe.&lt;/p&gt;
&lt;p&gt;Beyumbe is an experimental / lab software layer that provides most of the .NET Core plumbing for Umbraco: bootstrapping the application, hosting, dependency injection, filesystems, logging, background-tasking, routing, etc.&lt;/p&gt;
&lt;p&gt;Umbraco sits on top of this layer, pretty much unchanged, and provides the content cache, its pipeline and services, etc&amp;mdash;everything that is required to &lt;em&gt;publish&lt;/em&gt; content. It &lt;em&gt;does&lt;/em&gt; run its distributed cache, for instance.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/2eqdklef/docker-128.png" alt="" class="img-right" /&gt;&lt;/p&gt;
&lt;p&gt;One of the benefits of running a pure .NET Core site, apart from the excitement, is that it can be turned into a Docker container. This site now also has a C-side (can you picture this?) at &lt;a href="http://c.zpqrtbnk.net"&gt;c.zpqrtbnk.net&lt;/a&gt;. It runs as a Linux Docker container on Amazon AWS &lt;a href="https://aws.amazon.com/fr/fargate/"&gt;Fargate&lt;/a&gt; service. It is &lt;em&gt;also&lt;/em&gt; part of the load-balancing scenario, and updates with the other sides.&lt;/p&gt;
&lt;p&gt;You might notice that this C-side does not render images. Fargate in a compute engine, which simply executes containers. It does not yet support mounting filesystems into containers, and this prevents us from sharing a common media directory. The &lt;a href="https://github.com/aws/containers-roadmap/issues/53"&gt;feature&lt;/a&gt; is currently &amp;quot;in progress&amp;quot; at Amazon, yet with no ETA.&lt;/p&gt;
&lt;p&gt;Azure does seem to support mounting Azure Files shares into Azure Containers, so it may be easier on Azure. Unfortunately, I don't really have time to experiment on both platforms at the moment.&lt;/p&gt;
&lt;h4&gt;Next?&lt;/h4&gt;
&lt;p&gt;Beyumbe needs some love and polish to be able to support Umbraco in a robust way, as the whole thing was put together in a &lt;em&gt;very&lt;/em&gt; short time. But it is slowly getting there.&lt;/p&gt;
&lt;p&gt;As for Umbraco itself, most of the &lt;code&gt;Umbraco.Core&lt;/code&gt; project is ported, but work remain to deal with configuration, identity &amp;amp; security, and the runtime / maindom.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Umbraco.Web&lt;/code&gt; project is an entirely different beast. Only the very basic minimum, required to render content, has been ported. Everything else, from trees to controllers, WebApi to healthchecks, you name it, needs to be ported.&lt;/p&gt;
&lt;p&gt;Umbraco on .NET Core? Not fully there yet. But a nice project.&lt;/p&gt;
</description>
      <pubDate>Mon, 23 Sep 2019 19:20:00 Z</pubDate>
      <a10:updated>2019-09-23T19:20:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1272</guid>
      <link>http://www.zpqrtbnk.net/posts/umbraco-life-experiment/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <category>life</category>
      <title>Umbraco Life Experiment</title>
      <description>&lt;p&gt;A few months ago I announced I would be leaving HQ and transitioning back to the community side of Umbraco, end of September. People assumed I had some sort of a Grand Plan, an amazing business idea&amp;mdash;but the reality is more complex.&lt;/p&gt;
&lt;p&gt;Let's say I wanted to be closer to community and client work, in order to contribute in a more direct and effective way on various tools, features and topics that have been lagging for some time. With the goal of helping Umbraco be a strong, reliable yet simple platform for pro &amp;amp; advanced users&amp;mdash;and friendly, of course.&lt;/p&gt;
&lt;p&gt;And... the roadmap was not much clearer than that.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/2xefatm1/roadmap-blur-fit-600x120x1x1-0x0x0x0-75.png?hmac=5b4160e635a212431c152d8f68209d99bac34720e3818979f05badaa9c12f806" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Over the past 3 months, I have had numerous conversations with many members of the community, to find out what people valued and needed, and how they imagined these services could be delivered. Thanks to the thelp of those precious friends, I am now ready to introduce...&lt;/p&gt;
&lt;h4&gt;The Experiment&lt;/h4&gt;
&lt;p&gt;I should be looking for a new role (.NET/C#/architecture), really. At least that is what all my &amp;quot;entreprise&amp;quot; friends tell me. But before I do, I want to try something.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Services:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As of October 1st, I am immediately available for .NET work, as freelance. Umbraco, non-Umbraco, technical, less technical (I have spent a good deal of my life managing projects, too).&lt;/p&gt;
&lt;p&gt;Umbraco-wise, I provide &lt;strong&gt;Architecture Guiding&lt;/strong&gt; and &lt;strong&gt;Troubleshooting Guiding&lt;/strong&gt; services. Here, &lt;em&gt;guiding&lt;/em&gt; means working &lt;em&gt;with you&lt;/em&gt;, advising and teaching, on real cases, to reach solutions. Per hour, or per day, and optionally on-site. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder"&gt;Models Builder&lt;/a&gt;, and any other tools I may release, &lt;strong&gt;remains open source, and free&lt;/strong&gt;. They are distributed under the MIT license, &lt;strong&gt;but with a twist&lt;/strong&gt;. If you use them in any way that allows you to make money, directly or indirectly, and/or if you expect any kind of support, you are morally required to purchase a...&lt;/p&gt;
&lt;h4&gt;ZpqrtBnk General License&lt;/h4&gt;
&lt;p&gt;Everything may be open, but I still need a way to secure an income. Therefore, much alike Poul-Henning Kamp's &lt;a href="http://phk.freebsd.dk/VML/"&gt;Varnish Moral License&lt;/a&gt;, I am introducing the &lt;strong&gt;ZpqrtBnk General License&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It works like this: you tell me that you want to purchase a license. You &lt;em&gt;set your price&lt;/em&gt;. I send you an invoice from my &lt;a href="https://www.pilotine.com/en/"&gt;company&lt;/a&gt; (official, proper company invoice, handling VAT numbers etc). You pay the invoice. You are on the list.&lt;/p&gt;
&lt;p&gt;You then have the moral right to use the tools I release. You can expect them to be maintained, bugs to be fixed, questions to be answered, and feature requests to be considered.&lt;/p&gt;
&lt;p&gt;In addition, you ensure that I can keep improving people's Umbraco and .NET lives, be it on the community Slack, on Our, at meetups and festivals, or by fixing bugs, implementing features, etc.&lt;/p&gt;
&lt;p&gt;This is not a Make Money Fast scheme; the goal is to maintain my income. PHK is radical about it, and publishes his accounting status (eg, &lt;a href="http://phk.freebsd.dk/VML/2019/"&gt;2019&lt;/a&gt;). I don't know exactly how I will do it, but the plan is to be transparent too.&lt;/p&gt;
&lt;p&gt;Browse to the &lt;a href="http://www.zpqrtbnk.net/zpqrtbnk-general-license/" title="ZpqrtBnk General License"&gt;ZpqrtBnk General License&lt;/a&gt; page for infos and FAQs. Or to the &lt;a href="http://www.zpqrtbnk.net/zpqrtbnk-general-license/questions/" title="General License Questions"&gt;General License Questions&lt;/a&gt; for even more questions.&lt;/p&gt;
&lt;h4&gt;Ah, but...&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This is never going to work. People don't pay for what they can have for free. Who do you think you are? If I need to pay I am going to build it myself! You cannot enforce your license anyways. You cannot make a living of it. Others have tried.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;True. And reasons why the whole thing is an &lt;em&gt;experiment&lt;/em&gt;. I am interested in seeing what happens, but I am not completely naïve. Sure, I want free, open-source software, sponsored by people who value it. I don't want to issue activation codes, or hear about developers having to use &lt;a href="https://www.jetbrains.com/decompiler/"&gt;dotPeek&lt;/a&gt; to figure out issues in my private code, etc.&lt;/p&gt;
&lt;p&gt;But, this: &lt;strong&gt;noone is getting anything for free&lt;/strong&gt;. Either it works, or I have to stop and humbly move on to something else&amp;mdash;no offense. It's as simple. It's an experiment, it's a real challenge for my &lt;a href="https://en.wikipedia.org/wiki/Impostor_syndrome"&gt;impostor syndrome&lt;/a&gt;, but I want to at least try it.&lt;/p&gt;
&lt;p&gt;Models Builder has a new &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder/milestone/20"&gt;milestone&lt;/a&gt; and work-in-progress: a new, autonomous version, adding features to the built-in version. But&amp;mdash;that is only going to happen if my family can eat ;-)&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/i13nap2j/open-road-fit-600x180x1x1-0x0x0x0-75.jpg?hmac=b5446af7f089b0cfec8bd1bc733695e41eeac2ef308c07eedebd8e5b64c10658" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Current balance is zero, and I have approximatively zero autonomy beyond October.&lt;/p&gt;
&lt;p&gt;Let's see where this goes.&lt;/p&gt;
</description>
      <pubDate>Fri, 13 Sep 2019 19:00:00 Z</pubDate>
      <a10:updated>2019-09-13T19:00:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1278</guid>
      <link>http://www.zpqrtbnk.net/posts/umbraco-814-breaking-models-builder/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <title>Umbraco 8.1.4 Breaking &amp; Models Builder</title>
      <description>&lt;p&gt;&lt;em&gt;UPDATED: the proposed workaround has been simplified, see at the bottom of this post.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Umbraco 8.1.4 release fixes issue &lt;a href="https://github.com/umbraco/Umbraco-CMS/issues/6033"&gt;#6033&lt;/a&gt; but introduces a breaking change.&lt;/p&gt;
&lt;p&gt;Up until this release, when a media picker was configured to pick only images, the corresponding property value converter would report the property type as &lt;code&gt;Image&lt;/code&gt; or &lt;code&gt;IEnumerable&amp;lt;Image&amp;gt;&lt;/code&gt; and Models Builder would generate the property as (in &lt;code&gt;MyModel.generated.cs&lt;/code&gt;):&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public partial class MyModel
{
  // ...

  [ImplementPropertyType(&amp;quot;myImage&amp;quot;)]
  public Image MyImage
    =&amp;gt; this.Value&amp;lt;Image&amp;gt;(&amp;quot;myImage&amp;quot;);

  [ImplementPropertyType(&amp;quot;myImages&amp;quot;)]
  public IEnumerable&amp;lt;Image&amp;gt; MyImages
    =&amp;gt; this.Value&amp;lt;IEnumerable&amp;lt;Image&amp;gt;&amp;gt;(&amp;quot;myImages&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Thus allowing you to write:&lt;/p&gt;
&lt;pre class="prettyprint lang-txt"&gt;&lt;code&gt;&amp;lt;img src=&amp;quot;@Model.MyImage.GetCropUrl(&amp;quot;crop&amp;quot;)&amp;quot;
     alt=&amp;quot;@Model.MyImage.AltDescription&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unfortunately, that was based on the assumption that, with this configuration, the media picker would only allow media of type &amp;quot;image&amp;quot; (or anything inheriting &amp;quot;image&amp;quot;) to be picked. In reality, it seems that the media picker has different rules and allows various types of media to be picked.&lt;/p&gt;
&lt;p&gt;As a consequence, users would see nasty YSODs when picking anything that would &lt;em&gt;not&lt;/em&gt; inherit from &amp;quot;image&amp;quot;, as it would of course not fit within an &lt;code&gt;IEnumerable&amp;lt;Image&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The fix that was introduced forces the property value converter to report the property type as &lt;code&gt;IPublishedContent&lt;/code&gt; or &lt;code&gt;IEnumerable&amp;lt;IPublishedContent&amp;gt;&lt;/code&gt; no matter what can be picked. Alas, that breaks the existing Models Builder properties. And, if you re-generate models, what was &lt;code&gt;Image&lt;/code&gt; becomes &lt;code&gt;IPublishedContent&lt;/code&gt; and you lose the direct access to properties such as width or height.&lt;/p&gt;
&lt;h4&gt;Workaround&lt;/h4&gt;
&lt;p&gt;However, assuming that you know that you are only going to pick images, you do &lt;em&gt;not&lt;/em&gt; want to clutter your views with casts or non-strongly-typed property accesses.&lt;/p&gt;
&lt;p&gt;The workaround to keep all your views unchanged and clean, consists in declaring your own implementations of these properties, in a partial class, alongside the existing models. Models Builder will detect them, and not generate anything. You want (in &lt;code&gt;MyModel.cs&lt;/code&gt;):&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;public partial class MyModel
{
  [ImplementPropertyType(&amp;quot;myImage&amp;quot;)]
  public Image MyImage
    =&amp;gt; this.Value&amp;lt;IPublishedContent&amp;gt;(&amp;quot;myImage&amp;quot;) as Image;

  [ImplementPropertyType(&amp;quot;myImages&amp;quot;)]
  public IEnumerable&amp;lt;Image&amp;gt; MyImages
    =&amp;gt; this.Value&amp;lt;IEnumerable&amp;lt;IPublishedContent&amp;gt;&amp;gt;(&amp;quot;myImages&amp;quot;)
           .OfType&amp;lt;Image&amp;gt;();
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This can be tedious, though, if you have a lot of models.&lt;/p&gt;
&lt;h4&gt;Workaround (2)&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;UPDATE: This workaround works but is too complex, for no reason. Read it, then see the next workaround for the simple solution.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Alternatively, there is a more radical approach, if you are brave enough. Get the code for &lt;code&gt;MediaPickerValueConverter&lt;/code&gt; from 8.1.3, drop it into your own solution, and use a composer to use it in place of the one that ships with 8.1.4:&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;using UmbracoConverters = Umbraco.Web.PropertyEditors.ValueConverters;

public void Compose(Composition composition)
{
  composition.PropertyValueConverters()
    .Remove&amp;lt;UmbracoConverters.MediaPickerValueConverter&amp;gt;()
    .Append&amp;lt;MyConverters.MediaPickerConverter&amp;gt;()
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Everything will be back to normal, and that is probably what I am going to do on this site. But then of course, you end up running with a non-standard converter.&lt;/p&gt;
&lt;h4&gt;Workaround (3)&lt;/h4&gt;
&lt;p&gt;Same as above, get the code for &lt;code&gt;MediaPickerValueConverter&lt;/code&gt; from 8.1.3, drop it into your own solution, and make sure you remove its &lt;code&gt;[DefaultPropertyValueConverter]&lt;/code&gt;. That's it. No need for a composer. Since your converter is not &amp;quot;default&amp;quot;, it will override the default one.&lt;/p&gt;
&lt;p&gt;And, even better, you can use the converter posted by Ronald in &lt;a href="https://github.com/umbraco/Umbraco-CMS/issues/6033#issuecomment-528334114"&gt;this comment&lt;/a&gt; on the original GitHub issue. It tries to mitigate the issue in a nice way.&lt;/p&gt;
&lt;p&gt;I am afraid there is no ideal, immediate solution. In a perfect world... the media picker should be fixed, so one can indicate a (base) type to be picked, and so that only media of that type can be picked...&lt;/p&gt;
</description>
      <pubDate>Wed, 04 Sep 2019 16:40:00 Z</pubDate>
      <a10:updated>2019-09-04T16:40:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1273</guid>
      <link>http://www.zpqrtbnk.net/posts/missing-folders-in-umbraco-tree/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <title>Missing Folders in Umbraco Tree</title>
      <description>&lt;p&gt;On this very site, which originally started as a v7 site and has slowly been upgraded to the latest 8.1 release, something weird started happening. Some media folders stopped showing in the media tree left), although they would still show in the media panel (right).&lt;/p&gt;
&lt;p&gt;So: the media folders still existed, but they just did not show in trees.&lt;/p&gt;
&lt;p&gt;I am pretty sure it worked with 8.0, and stopped working with 8.1. Which is strange, as the &lt;a href="https://github.com/umbraco/Umbraco-CMS/issues/6158"&gt;original issue&lt;/a&gt; seems to target the 7-to-8 upgrade. Anyways. I just wanted to share the cause, and the fix.&lt;/p&gt;
&lt;p&gt;The cause is missing rows in the &lt;code&gt;umbracoMediaVersion&lt;/code&gt; table for these folders. The fix consists in inserting these missing rows again.&lt;/p&gt;
&lt;p&gt;This is exactly what the following SQL does:&lt;/p&gt;
&lt;pre class="prettyprint lang-sql"&gt;&lt;code&gt;insert into umbracoMediaVersion (id, path)
select VersionId, NULL
from (

    select n.id NodeId, n.Text Name, ct.alias Alias, cv.id VersionId, mv.id MvId, mv.path MvPath
    from umbracoNode n
    join umbracoContent c on n.id=c.nodeId
    join cmsContentType ct on c.contentTypeId=ct.nodeId
    join umbracoContentVersion cv on n.id=cv.nodeId
    left outer join umbracoMediaVersion mv on cv.id=mv.id
    where n.nodeObjectType='B796F64C-1F99-4FFB-B886-4BF4BC011A9C'

    and ct.alias='Folder' -- only folders
    and mv.id is null -- that dont have the required row
) x
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that you may want to run the inner query first, just to verify that your database is indeed missing these rows.&lt;/p&gt;
</description>
      <pubDate>Fri, 30 Aug 2019 14:55:00 Z</pubDate>
      <a10:updated>2019-08-30T14:55:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1236</guid>
      <link>http://www.zpqrtbnk.net/posts/models-builder-extension/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <title>Models Builder Extension</title>
      <description>&lt;p&gt;One way to generate models for Umbraco with the &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder"&gt;Models Builder&lt;/a&gt; tool has long been to use the Visual Studio &lt;a href="https://marketplace.visualstudio.com/items?itemName=ZpqrtBnk.UmbracoModelsBuilderCustomTool"&gt;Custom Tool&lt;/a&gt;. This extension provides a &lt;em&gt;Single File Generator&lt;/em&gt; which can be used just as any standard Visual Studio Custom Tool.&lt;/p&gt;
&lt;p&gt;Meanwhile, Microsoft has introduced .NET Core and is slowly evolving the structure of its Visual Studio projects, and updating the tooling along the way. Let us say that the road is, sometimes, a bit unclear and hard to follow.&lt;/p&gt;
&lt;p&gt;Using a single file generator to generate multiple files has traditionally been &amp;quot;the way&amp;quot; to do it, but it has also always been hackish, and as &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder/issues/210"&gt;this issue&lt;/a&gt; and others made obvious. It is becoming harder and harder to support with the new &amp;quot;NET.Sdk&amp;quot; project types.&lt;/p&gt;
&lt;p&gt;I am, therefore, sad to announce that the Custom Tool is now dead. But do not despair! It is superceeded by the &lt;em&gt;Extension&lt;/em&gt;, which, essentially, provides exactly the same service, in a slightly different way.&lt;/p&gt;
&lt;h4&gt;Migrating&lt;/h4&gt;
&lt;p&gt;In order to migrate to the extension, first uninstall the Custom Tool extension, then install the Extension.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/z2eh5f31/snap5-mw-600.png?hmac=3585ce9aea8a0f94046d4d132a7dd49ae36696c524eaadb396d4dd15f45ba845" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Then, the only difference is that models are not generated under a C# file anymore, but under a special placeholder. You &lt;em&gt;probably&lt;/em&gt; don't need the root C# file anymore, unless it contained attributes to configure models. The next section will explain it all.&lt;/p&gt;
&lt;p&gt;The configuration (in &lt;strong&gt;Tools&lt;/strong&gt; | &lt;strong&gt;Options&lt;/strong&gt;) remain the same.&lt;/p&gt;
&lt;h4&gt;Using the extension&lt;/h4&gt;
&lt;p&gt;Right-click on the folder containing your models, both the generated and non-generated partials. Select &lt;strong&gt;Add&lt;/strong&gt; | &lt;strong&gt;New item...&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/brxnkueo/snap1-mw-600.png?hmac=8e721d7a54cd74f29244956bf9cfbc9b2ab2dc493a0255f4da7787042803ed40" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Select &lt;strong&gt;Visual C#&lt;/strong&gt;, &lt;strong&gt;Umbraco&lt;/strong&gt;, and add a new Umbraco Models placeholder named, for instance, &lt;code&gt;Models.mb&lt;/code&gt;. The name is of no importance, only the extension is.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/kulhrg0x/snap2-mw-600.png?hmac=dc7529e7dbb9fd9efde371ec03f184dc318f078832abeda895733097fd677ce8" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Now, right-click on that new &lt;code&gt;Models.mb&lt;/code&gt; file and select &lt;strong&gt;Build Models&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/seun413e/snap3-mw-600.png?hmac=e013dc44ec2e4cb5c869b3eec68eaed715537ac308c84fb5a5f802aafca7a511" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;The extension connects to the running site, retrieves models, and adds them to the project, nicely nested under the models placeholder.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/sebh1i1h/snap4-mw-600.png?hmac=ca2139e13b9250d054de236904967c8400fa9a8fdfbdee4725dadd228aa54a44" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;h4&gt;Configuring&lt;/h4&gt;
&lt;p&gt;By default, models are generated in a namespace derived from the root namespace of the project, and the folders structure. That, and various other aspects of models, can be configured via attributes.&lt;/p&gt;
&lt;p&gt;Add a file &lt;code&gt;Models.cs&lt;/code&gt; (or any other name, as long as it is a C# file) to the models folder, containing the following code (it does not need to contain a class definition!):&lt;/p&gt;
&lt;pre class="prettyprint lang-csharp"&gt;&lt;code&gt;using Umbraco.ModelsBuilder;

[assembly:ModelsNamespace(&amp;quot;MyOwnNamespace&amp;quot;)]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That file will be parsed, and models will be generated in &lt;code&gt;MyOwnNamespace&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Refer to the (kinda obsolete, soon to be updated) &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/ModelsGenerationConfiguration"&gt;documentation&lt;/a&gt; for more attributes.&lt;/p&gt;
&lt;h4&gt;What's Next?&lt;/h4&gt;
&lt;p&gt;As mentioned above, the documentation is kinda obsolete. There are tons of things that can be configured, and noone is aware of it. Next effort will be to cleanup the documentation, and implement some long-requested features.&lt;/p&gt;
&lt;p&gt;Stay tuned!&lt;/p&gt;
</description>
      <pubDate>Fri, 19 Jul 2019 09:51:01 Z</pubDate>
      <a10:updated>2019-07-19T09:51:01Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1232</guid>
      <link>http://www.zpqrtbnk.net/posts/solutionbook-for-visual-studio-2019/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <title>SolutionBook for Visual Studio 2019</title>
      <description>&lt;p&gt;For many years, I have used the excellent &lt;a href="https://marketplace.visualstudio.com/items?itemName=Herdo.SolutionStartPage"&gt;SolutionStartPage&lt;/a&gt; extension for Visual Studio 2015 and 2017. This extension replaces the default Start Page with a customizable view of all my solutions. It is like a giant start menu: fire Visual Studio, pick the solution you want to work on.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/kjqmhypy/2019-06-20-11_53_32-start-page-microsoft-visual-studio-_.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Alas, Visual Studio 2019 has replaced the start page with an entirely different start &lt;em&gt;window&lt;/em&gt;, which cannot really be modified, entirely breaking SolutionStartPage (see issue &lt;a href="https://github.com/Herdo/SolutionStartPage/issues/25"&gt;#25&lt;/a&gt;). There are a few discussions about the future of the start page on Visual Studio's developper community (see for instance &lt;a href="https://developercommunity.visualstudio.com/idea/531110/allow-cutomization-or-extension-of-the-new-start-w.html"&gt;this one&lt;/a&gt;) but it does not seem that Microsoft is going to address the situation anytime soon.&lt;/p&gt;
&lt;p&gt;And, this makes working with Visual Studio 2019 way more annoying. I was really used to just firing Visual Studio and opening a frequently-used solution, without having to think about where it is on my disk.&lt;/p&gt;
&lt;h4&gt;Problem &amp;rarr; Solution&lt;/h4&gt;
&lt;p&gt;So... I spent a couple of evenings putting together a replacement for Visual Studio 2019, and... &lt;strong&gt;SolutionBook&lt;/strong&gt; is now available on the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ZpqrtBnk.SolutionBook"&gt;Visual Studio MarketPlace&lt;/a&gt; with code in its own &lt;a href="https://github.com/zpqrtbnk/SolutionBook"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This extension installs a new Visual Studio tool window, which can be displayed with &lt;strong&gt;View&lt;/strong&gt; | &lt;strong&gt;Other Windows&lt;/strong&gt; | &lt;strong&gt;SolutionBook&lt;/strong&gt;, and docked anywhere&amp;mdash;I dock mine to the left, with the already existing &lt;strong&gt;Toolbox&lt;/strong&gt; tool window.&lt;/p&gt;
&lt;p&gt;It lets you organize your solutions in a tree. It's always there when Visual Studio opens, and double-clicking a solution just opens it. You can add and remove solutions, move them around, group them in folders, etc. That is all. It saves me tons of time. YMMV.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/media/xp2fmcfm/2019-06-20-11_44_43-umbraco-8-_.png" alt="" class="img-center" /&gt;&lt;/p&gt;
&lt;p&gt;Note: you &lt;em&gt;have&lt;/em&gt; to save your changes using the toolbar button. Saving is &lt;em&gt;not&lt;/em&gt; automatic. And it &lt;em&gt;won't&lt;/em&gt; tell you if you forget. And the &lt;em&gt;Refresh&lt;/em&gt; toolbar buttons reloads from disk. This is how concurrency between multiple Visual Studio instances is (not) managed.&lt;/p&gt;
&lt;p&gt;Another note: this was all quickly put together. WPF is fantastic but also hard. There may be issues, and it's probably not the cleanest code I have produced. Saving and refreshing should be all automagic. Feel free to contribute!&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</description>
      <pubDate>Thu, 20 Jun 2019 12:10:00 Z</pubDate>
      <a10:updated>2019-06-20T12:10:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1209</guid>
      <link>http://www.zpqrtbnk.net/posts/tide-flows/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <category>life</category>
      <title>Tide Flows</title>
      <description>&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/muxervti/nh-email-4-mw-600.png?hmac=96586d0e0787c7851df16fa77e20ac82dbf715e1d8a03dab3f9f8179d632ca64" alt="" class="img-right" /&gt;&lt;/p&gt;
&lt;p&gt;This is the very first email I have received from Niels Hartvig, founder of the &lt;a href="https://www.umbraco.com"&gt;Umbraco CMS&lt;/a&gt;, answering some trivial questions I had asked on the contact form, while evaluating Umbraco for a client.&lt;/p&gt;
&lt;p&gt;I attended my first Codegarden the next Spring, still trying to figure out how the whole thing was supposed to work, and fell in love with the community. I discovered a honest software ecosystem that did not try to hide its defects, but instead radiated with energy and ideas, and made things possible. Being the &amp;quot;prudent&amp;quot; guy, this felt quite a safe approach.&lt;/p&gt;
&lt;p&gt;And so, I started fixing these defects, one small CompletelyBroken™ item at a time. And I started dreaming, about a version that would be cleaner and more stable and more predictable. A few years later, HQ was part-time sponsoring my clean up effort. A few more years later, it was full-time. And by my 10th Codegarden, version 8 was out.&lt;/p&gt;
&lt;p&gt;Today, after just a bit more than 4 full-time years with HQ, I have decided it's time for a change for me, time for the tide to turn, and I'll be transitioning back to the community side of Umbraco.&lt;/p&gt;
&lt;p&gt;Architecting &amp;quot;v8&amp;quot; and the inners of Deploy, with amazing colleagues, has been a fantastic experience. Built upon the tons of ideas, concerns, thoughts, experiments that arised during my client work, using Umbraco to build sites, discussing with other users. Releasing the result of it all has been quite a milestone. And then: what's next? How can it happen? I feel this need, to get closer to clients and community again, gather new ideas, explore new directions, get inspired.&lt;/p&gt;
&lt;p&gt;So, what now? For me, it means that I'll be working for the HQ, ensuring a smooth transition, until the end of September. Then, I'll be &lt;a href="http://www.pilotine.com"&gt;freelance&lt;/a&gt; again, looking for opportunities. So, if you have any Umbraco job that you need some help on, or any use for a .NET / Umbraco guy, or want to sponsor some Open Source work, or talk about collaboration... drop me a line.&lt;/p&gt;
&lt;p&gt;Before this post ends, I'd like to thank Niels and Per for trusting me, and offering me the opportunity to make some of my dreams come true&amp;mdash;and for the amazing colleagues who helped me on the way. It's been fun. And I also need to thank some truly helpful friends&amp;mdash;you know who you are.&lt;/p&gt;
&lt;p&gt;I have always prefered the Atlantic to the Mediterranean because of tides. Twice a day, everything moves, everything changes, everything is clean again. Scary. Exciting. But that is what living is, really.&lt;/p&gt;
</description>
      <pubDate>Thu, 06 Jun 2019 14:45:00 Z</pubDate>
      <a10:updated>2019-06-06T14:45:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1210</guid>
      <link>http://www.zpqrtbnk.net/posts/remember-rick-dangerous/</link>
      <author>sgay@pilotine.com</author>
      <category>hacks</category>
      <category>xrick</category>
      <title>Remember Rick Dangerous?</title>
      <description>&lt;p&gt;Way before Lara Croft, back in the 1980's and early 1990's, Rick Dangerous was the Indiana Jones of computer games, running away from rolling rocks, avoiding traps, from South America to a futuristic missile base via Egypt and the Schwarzendumpf castle.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/ejhpezsh/rick-dangerous-mw-600.png?hmac=e5d479970e9c7de9b321a380d375f38ac8c294c638ac0544db6a74c729c7e5e4" alt="" class="img-right" /&gt;&lt;/p&gt;
&lt;p&gt;Produced by Firebird and developed by Core Design (both long gone now), this platform game was conceived by Terry Lloyd and &lt;a href="https://www.simonphipps.com/games/rickdangerous/"&gt;Simon Phipps&lt;/a&gt; and released in 1989&amp;mdash;see the &lt;a href="http://www.rickdangerous.co.uk/main.htm"&gt;Rick Dangerous Resurrected&lt;/a&gt; site for tons of details.&lt;/p&gt;
&lt;p&gt;I fell in love with the game around 1990, and started to crack and reverse the IBM PC (x86 CPU) version. No &lt;a href="https://www.hex-rays.com/products/ida/"&gt;IDA Pro&lt;/a&gt; nor emulators at that time: all I had was plain MS-DOS &lt;a href="https://en.wikipedia.org/wiki/Debug_(command)"&gt;debug&lt;/a&gt; command, and paper. But it was pretty magic to understand how it all worked.&lt;/p&gt;
&lt;h4&gt;xrick&lt;/h4&gt;
&lt;p&gt;Ten years later, around 2000, I decided to port the game from assembly to C, so that it could run on the now ubiquitous Windows platform, and on Linux, thanks to the &lt;a href="https://www.libsdl.org/"&gt;SDL&lt;/a&gt; library. And xrick was born. I also reversed the Atari ST (68k CPU) version of the game, in order to extract the much nicer graphics and sounds.&lt;/p&gt;
&lt;p&gt;I &lt;a href="http://www.bigorno.net/xrick"&gt;released a few versions&lt;/a&gt;, including the December 12, 2002 final version that was complete and has since been ported over to Windows, Linux, BeOs, Amiga, QNX, Nintendo DS, GameCube, etc. and all sorts of gaming consoles, phones and devices.&lt;/p&gt;
&lt;p&gt;And then, nothing much happened. A &lt;a href="http://rickdangerousflash.free.fr/"&gt;Rick Dangerous Flash&lt;/a&gt;  version was released, and I cannot remember whether it was based upon xrick or not. Few people submitted fixes, but I had no time, really.&lt;/p&gt;
&lt;h4&gt;2019&lt;/h4&gt;
&lt;p&gt;And then... it is now 2019, &lt;a href="https://webassembly.org/"&gt;WebAssembly&lt;/a&gt; has become more mainstream, and &lt;a href="https://emscripten.org/"&gt;emscripten&lt;/a&gt; has &lt;a href="https://www.libsdl.org/"&gt;SDL2&lt;/a&gt; support, and there was this challenge: can xrick run natively in the browser?&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/3dyhzt44/xrick-mw-600.png?hmac=e8bc88a11b7e51dabbdd2218c57a15417a6a3bbc5584100aa383448c16f720c1" alt="" class="img-right" /&gt;&lt;/p&gt;
&lt;p&gt;Well, the answer is, &lt;strong&gt;yes it can&lt;/strong&gt;! Go play at &lt;a href="https://www.xrick.net"&gt;xrick.net&lt;/a&gt;! It should work on any recent-enough browser that supports WebAssembly.&lt;/p&gt;
&lt;p&gt;All I had to do was... port from SDL1 to SDL2, understand how the rendering loop works in WebAssembly, and tweak a few things so emscripten could compile the code. Which is now available in its own &lt;a href="https://github.com/zpqrtbnk/xrick"&gt;GitHub repository&lt;/a&gt;. Feel free to contribute!&lt;/p&gt;
&lt;p&gt;And before you ask (because that's the most FAQ): no, I do &lt;em&gt;not&lt;/em&gt; have reversed Rick Dangerous 2, and certainly do &lt;em&gt;not&lt;/em&gt; have time to do so. You'll have to wait until I retire.&lt;/p&gt;
</description>
      <pubDate>Wed, 05 Jun 2019 19:45:00 Z</pubDate>
      <a10:updated>2019-06-05T19:45:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
    <item>
      <guid isPermaLink="false">1193</guid>
      <link>http://www.zpqrtbnk.net/posts/do-you-speak-logfile/</link>
      <author>sgay@pilotine.com</author>
      <category>umbraco</category>
      <title>Do You Speak LogFile?</title>
      <description>&lt;p&gt;If you are using Umbraco v8, you probably have noticed that the beautiful text logfiles containing lines as explicit and helpful as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2019-04-04 10:31:35,309 [P3248/D10/T5] INFO Umbraco.Core.Logging.OwinLogger - [Information] Event Id: 0, State: Login attempt failed for username support@example.com from IP address ::1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;have turned into the following uber-geekish gibberish&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{&amp;quot;@t&amp;quot;:&amp;quot;2019-04-04T10:31:35.3099502Z&amp;quot;,&amp;quot;@mt&amp;quot;:&amp;quot;[{EventType}] Event Id: {EventId}, State: {State}&amp;quot;,&amp;quot;EventType&amp;quot;:&amp;quot;Information&amp;quot;,&amp;quot;EventId&amp;quot;:0,&amp;quot;State&amp;quot;:&amp;quot;Login attempt failed for username support@webwonders.nl from IP address ::1&amp;quot;,&amp;quot;SourceContext&amp;quot;:&amp;quot;Umbraco.Core.Logging.OwinLogger&amp;quot;,&amp;quot;ProcessId&amp;quot;:3248,&amp;quot;ProcessName&amp;quot;:&amp;quot;iisexpress&amp;quot;,&amp;quot;ThreadId&amp;quot;:5,&amp;quot;AppDomainId&amp;quot;:10,&amp;quot;AppDomainAppId&amp;quot;:&amp;quot;LMW3SVC2ROOT&amp;quot;,&amp;quot;MachineName&amp;quot;:&amp;quot;DESKTOP-BPQ57JN&amp;quot;,&amp;quot;Log4NetLevel&amp;quot;:&amp;quot;INFO &amp;quot;,&amp;quot;HttpRequestNumber&amp;quot;:3,&amp;quot;HttpRequestId&amp;quot;:&amp;quot;0aa853af-825e-4f4a-990b-2744dc37899a&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and that is... a Good Thing! Indeed, these Json log files can easily be parsed by the new, shiny, built-in log viewer in the Settings section&amp;mdash;or by any tool that you would want to use to parse log files.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.zpqrtbnk.net/imgx/ssid2qsn/logviewer-mw-600.png?hmac=2d310b4ca5cfee6ce3f37871ea4061e0327e3a188b8a95bf61c2461511ce821c" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The drawback is that these files are simply impossible to read outside of the log viewer.&lt;/p&gt;
&lt;p&gt;For instance, if you send your logfile to friends with the vain hope that they could be able to figure out why nothing works on your production site... they &lt;em&gt;may&lt;/em&gt; try to feed it to some Json-formatting tool but even then... it is pretty useless.&lt;/p&gt;
&lt;p&gt;And no, Google Translate does not speak logfile yet.&lt;/p&gt;
&lt;p&gt;But, do not despair! There is a way! Read &lt;a href="https://nblumhardt.com/2017/07/clef-tool/"&gt;this blog post&lt;/a&gt; and get &lt;a href="https://github.com/datalust/clef-tool"&gt;this tool&lt;/a&gt; named CLEF and use it to convert the Json file to the text version. I do it from the Git Bash shell and have created the following alias:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alias clef='/c/Program\ Files/CLEF\ Tool/clef.exe --format-template=&amp;quot;{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel}  {SourceContext} - {Message:lj}{NewLine}{Exception}&amp;quot; -i'
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which I use as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;clef useless.json &amp;gt; beautiful.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You would have to adapt it to your favorite shell (e.g. PowerShell...), of course, because nothing is free in this world, but that should be an easy task, and then you would be speaking logfile like a native.&lt;/p&gt;
&lt;p&gt;You're welcome.&lt;/p&gt;
</description>
      <pubDate>Thu, 04 Apr 2019 16:25:00 Z</pubDate>
      <a10:updated>2019-04-04T16:25:00Z</a10:updated>
      <a10:rights type="html">Copyright &amp;copy; 1985-2026 Stéphane Gay</a10:rights>
    </item>
  </channel>
</rss>