<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stefan Zipproth</title>
    <description>The latest articles on DEV Community by Stefan Zipproth (@acrion).</description>
    <link>https://dev.to/acrion</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2669462%2F0f2a5680-bb78-49c6-a307-6cc516204a3c.png</url>
      <title>DEV Community: Stefan Zipproth</title>
      <link>https://dev.to/acrion</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/acrion"/>
    <language>en</language>
    <item>
      <title>I built a C++ Reasoning Engine that holds 1.7TB of Knowledge in RAM – zelph v0.9.2</title>
      <dc:creator>Stefan Zipproth</dc:creator>
      <pubDate>Mon, 05 Jan 2026 20:34:44 +0000</pubDate>
      <link>https://dev.to/acrion/i-built-a-c-reasoning-engine-that-holds-17tb-of-knowledge-in-ram-zelph-v092-3i6i</link>
      <guid>https://dev.to/acrion/i-built-a-c-reasoning-engine-that-holds-17tb-of-knowledge-in-ram-zelph-v092-3i6i</guid>
      <description>&lt;p&gt;Hi DEV Community! 👋&lt;/p&gt;

&lt;p&gt;I’ve just released version 0.9.2 of &lt;strong&gt;zelph&lt;/strong&gt;, a semantic network system capable of encoding inference rules within the network itself.&lt;br&gt;
It’s open source and designed for high-performance logical reasoning.&lt;/p&gt;
&lt;h3&gt;
  
  
  What makes it special?
&lt;/h3&gt;

&lt;p&gt;In zelph, &lt;strong&gt;rules are facts&lt;/strong&gt;. Unlike traditional systems where logic is external code applied to data, zelph treats relation types (like "transitivity") as first-class nodes in the graph. This allows for powerful meta-reasoning where you can make statements &lt;em&gt;about&lt;/em&gt; statements.&lt;/p&gt;
&lt;h3&gt;
  
  
  A Taste of Logic: Try it yourself
&lt;/h3&gt;

&lt;p&gt;Before we talk about terabytes of data, let’s look at how it feels to use. zelph has an interactive CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Basic Inference&lt;/strong&gt;&lt;br&gt;
You can define facts and rules on the fly. Note that none of the items below are predefined; zelph learns them as you type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start the interactive shell&lt;/span&gt;
zelph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Berlin "is capital of" Germany
Germany "is located in" Europe

# Define a rule: If X is capital of Y, and Y is in Z, then X is in Z
X "is capital of" Y, Y "is located in" Z =&amp;gt; X "is located in" Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;«Berlin» «is located in» «Europe» ⇐ («Germany» «is located in» «Europe»), («Berlin» «is capital of» «Germany»)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;zelph automatically inferred the location of Berlin based on the rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Meta-Reasoning (Transitivity)&lt;/strong&gt;&lt;br&gt;
This is where it gets interesting. Instead of writing a specific rule for every transitive relation, we can define "transitivity" itself as a concept in the network.&lt;br&gt;
&lt;em&gt;(Note: &lt;code&gt;~&lt;/code&gt; is shorthand for "instance of" or "is a")&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Define a general rule for ANY transitive relation R
R ~ "transitive relation", X R Y, Y R Z =&amp;gt; X R Z

# Now, declare that "greater than" is a transitive relation
&amp;gt; ~ "transitive relation"

# Give it some numbers
6 &amp;gt; 5
5 &amp;gt; 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;«6» «&amp;gt;» «4» ⇐ («5» «&amp;gt;» «4»), («6» «&amp;gt;» «5»), («&amp;gt;» «~» «transitive relation»)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because &lt;code&gt;&amp;gt;&lt;/code&gt; is an instance of a transitive relation, zelph applied the meta-rule and deduced that 6 &amp;gt; 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Detecting Contradictions&lt;/strong&gt;&lt;br&gt;
You can also define what is &lt;em&gt;impossible&lt;/em&gt; using &lt;code&gt;!&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Rule: If X is opposite of Y, a thing A cannot be both X and Y
X "is opposite of" Y, A ~ X, A ~ Y =&amp;gt; !
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you (or an imported dataset) try to assert facts that violate this, zelph detects the logical contradiction immediately.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Benchmark: Debugging 1.7 TB of Knowledge
&lt;/h3&gt;

&lt;p&gt;To test the limits, I optimized zelph to process the entire &lt;strong&gt;Wikidata Knowledge Graph&lt;/strong&gt; (over 113 million entities). But this wasn't just a performance test—it was a logic audit.&lt;/p&gt;

&lt;p&gt;Using the rules described above (like disjointness and transitivity), zelph identified &lt;strong&gt;hundreds of megabytes of logical contradictions&lt;/strong&gt; hidden within the live Wikidata dataset.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Performance:&lt;/strong&gt; ~1000x speedup in reasoning compared to early prototypes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Scale:&lt;/strong&gt; A &lt;strong&gt;single-pass&lt;/strong&gt; analysis of the full graph (requires ~256 GB RAM for the full dump, but scales down for smaller tasks).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Results:&lt;/strong&gt; We detected massive amounts of &lt;strong&gt;Split Order Violations&lt;/strong&gt; (broken hierarchies) and &lt;strong&gt;Disjointness Errors&lt;/strong&gt; (items belonging to mutually exclusive categories).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can dive into the results and see the actual logical "bugs" found in the &lt;a href="https://zelph.org/grant-report" rel="noopener noreferrer"&gt;Grant Report&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now available everywhere
&lt;/h3&gt;

&lt;p&gt;Thanks to a recent sprint (and a Wikimedia Grant), you can install it natively to play with the logic engine yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Windows:&lt;/strong&gt; &lt;code&gt;choco install zelph&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;macOS:&lt;/strong&gt; &lt;code&gt;brew tap acrion/zelph &amp;amp;&amp;amp; brew install zelph&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Linux:&lt;/strong&gt; &lt;code&gt;pikaur -S zelph&lt;/code&gt; (AUR)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Future Directions: Lisp &amp;amp; "Code as Data"
&lt;/h3&gt;

&lt;p&gt;This is where I’d love your input.&lt;br&gt;
The current custom scripting language (shown above) works well, but I plan to embed a &lt;strong&gt;Lisp dialect&lt;/strong&gt; (specifically &lt;strong&gt;Fennel&lt;/strong&gt; or &lt;strong&gt;Janet&lt;/strong&gt;) to perfectly mirror the semantic network structure where rules and facts are identical nodes.&lt;/p&gt;

&lt;p&gt;This aligns perfectly with the "Code as Data" philosophy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Why Fennel?&lt;/strong&gt; Incredible performance (LuaJIT) and seamless synergy with my other project, &lt;a href="https://nexuslua.org" rel="noopener noreferrer"&gt;nexuslua&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Why Janet?&lt;/strong&gt; Modern, great macro system, clean C API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested in &lt;strong&gt;C++20&lt;/strong&gt;, &lt;strong&gt;Semantic Web&lt;/strong&gt;, or &lt;strong&gt;Lisp embedding&lt;/strong&gt;, check out the repo!&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/acrion/zelph" rel="noopener noreferrer"&gt;https://github.com/acrion/zelph&lt;/a&gt;&lt;br&gt;
🔗 &lt;strong&gt;Grant Report &amp;amp; Architecture:&lt;/strong&gt; &lt;a href="https://zelph.org/grant-report" rel="noopener noreferrer"&gt;https://zelph.org/grant-report&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;br&gt;
Stefan&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>algorithms</category>
      <category>wikidata</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Cbeam: Unmatched Concurrency, Cross-Library Data Sharing, and More in Modern C++</title>
      <dc:creator>Stefan Zipproth</dc:creator>
      <pubDate>Sat, 18 Jan 2025 14:30:38 +0000</pubDate>
      <link>https://dev.to/acrion/cbeam-unmatched-concurrency-cross-library-data-sharing-and-more-in-modern-c-33kf</link>
      <guid>https://dev.to/acrion/cbeam-unmatched-concurrency-cross-library-data-sharing-and-more-in-modern-c-33kf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cbeam.org" rel="noopener noreferrer"&gt;Cbeam&lt;/a&gt; is a modern, cross-platform, header-only C++ library designed to simplify concurrency, memory sharing, serialization, and more—without depending on Boost. It draws inspiration from Boost’s coding style but remains lightweight and easy to integrate on Linux, macOS, and Windows. Four standout features illustrate Cbeam’s capabilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous Message Dispatching&lt;/strong&gt; (using &lt;a href="https://cbeam.org/message_manager" rel="noopener noreferrer"&gt;&lt;code&gt;message_manager&lt;/code&gt;&lt;/a&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform Shared Memory&lt;/strong&gt; (using &lt;a href="https://cbeam.org/interprocess_shared_memory" rel="noopener noreferrer"&gt;&lt;code&gt;interprocess_shared_memory&lt;/code&gt;&lt;/a&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable Reference Counting Across Shared Libraries&lt;/strong&gt; (using &lt;a href="https://cbeam.org/stable_reference_buffer/" rel="noopener noreferrer"&gt;&lt;code&gt;stable_reference_buffer&lt;/code&gt;&lt;/a&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperable Containers Across Compiler Boundaries&lt;/strong&gt; (with &lt;a href="https://cbeam.org/interprocess_containers/" rel="noopener noreferrer"&gt;“stable interprocess” containers&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll take a closer look at &lt;code&gt;message_manager&lt;/code&gt; and show how it enables straightforward, thread-safe message handling. But first, here’s a quick overview of the other three “spotlight features”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform Shared Memory&lt;/strong&gt;: &lt;code&gt;interprocess_shared_memory&lt;/code&gt; unifies Windows (native file mapping) and Unix (POSIX &lt;code&gt;shm_open&lt;/code&gt;) shared memory under a simple API. No leftover OS objects to clean up and no complicated file permissions for &lt;code&gt;C:\ProgramData\boost_interprocess&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable Reference Counting&lt;/strong&gt;: &lt;a href="https://cbeam.org/stable_reference_buffer/" rel="noopener noreferrer"&gt;&lt;code&gt;stable_reference_buffer&lt;/code&gt;&lt;/a&gt; places the reference count in a safe, process-wide map, solving the classic issue where &lt;code&gt;std::shared_ptr&lt;/code&gt; across shared library boundaries can lead to mismatched counts and double frees.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperable Containers&lt;/strong&gt;: &lt;a href="https://cbeam.org/interprocess_containers/" rel="noopener noreferrer"&gt;“stable interprocess” containers&lt;/a&gt; (like &lt;a href="https://cbeam.org/doxygen/classcbeam_1_1container_1_1stable__interprocess__map.html" rel="noopener noreferrer"&gt;&lt;code&gt;stable_interprocess_map&lt;/code&gt;&lt;/a&gt;) allow sharing data between libraries or processes compiled with different toolchains. Serialization logic handles potential ABI mismatches.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might also explore &lt;a href="https://cbeam.org/nested_map" rel="noopener noreferrer"&gt;&lt;code&gt;nested_map&lt;/code&gt;&lt;/a&gt; for hierarchical data (configuration trees, JSON-like structures) if your application needs more flexible, nested storage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Dive: Asynchronous Message Dispatching with &lt;code&gt;message_manager&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Idea
&lt;/h3&gt;

&lt;p&gt;The Cbeam &lt;code&gt;message_manager&lt;/code&gt; helps you send messages to one or more handler threads. Each message type is identified by a numeric ID, and each ID can be associated with one or multiple handlers. Internally, &lt;code&gt;message_manager&lt;/code&gt; maintains safe queues, providing FIFO, FILO, or RANDOM dispatch order. It includes mechanisms to wait until all messages for a given ID have been processed, which is especially useful for clean synchronization points.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Not Just Use &lt;code&gt;std::thread&lt;/code&gt; and &lt;code&gt;std::condition_variable&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Manual threading requires you to handle queueing, synchronization, and error handling. With &lt;code&gt;message_manager&lt;/code&gt;, you reduce boilerplate and minimize risks like deadlocks or race conditions. It’s header-only, has no external dependencies, and works cross-platform, adding minimal performance overhead while significantly reducing the risk of concurrency bugs. In addition, &lt;code&gt;message_manager&lt;/code&gt; can integrate with &lt;a href="https://cbeam.org/doxygen/namespacecbeam_1_1serialization.html" rel="noopener noreferrer"&gt;Cbeam’s serialization features&lt;/a&gt; to pass data across shared libraries that may not be ABI-compatible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Example
&lt;/h3&gt;

&lt;p&gt;Below is a simplified prime-checking program to illustrate the design. We define two message IDs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;check_prime&lt;/code&gt;: A handler that checks if a number is prime and, if so, sends it to the second handler.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count_prime&lt;/code&gt;: A handler that increments a shared counter each time it receives a “prime” message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We enqueue numbers from 1 to 100,000, wait for all tasks to finish, then dispose the handlers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cbeam/concurrency/message_manager.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;atomic&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Quick prime test&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;check_prime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;count_prime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1) Create a message_manager that handles messages carrying a&lt;/span&gt;
    &lt;span class="c1"&gt;//    64-bit integer. (Side note: message_manager can integrate&lt;/span&gt;
    &lt;span class="c1"&gt;//    with serialization to pass data across shared libraries&lt;/span&gt;
    &lt;span class="c1"&gt;//    that might not be ABI-compatible.)&lt;/span&gt;
    &lt;span class="n"&gt;cbeam&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;concurrency&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;message_manager&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;atomic&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;prime_count&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// 2) Define a handler that increments the prime count.&lt;/span&gt;
    &lt;span class="c1"&gt;//    (Note that we ignore the actual number here — only the&lt;/span&gt;
    &lt;span class="c1"&gt;//    event matters.)&lt;/span&gt;
    &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count_prime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;prime_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// 3) Define a handler to check numbers and forward prime ones&lt;/span&gt;
    &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_prime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count_prime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// (You could register multiple add_handler calls with&lt;/span&gt;
    &lt;span class="c1"&gt;//  the same ID to distribute the work across multiple &lt;/span&gt;
    &lt;span class="c1"&gt;//  threads - just run the above code `n` times.)&lt;/span&gt;

    &lt;span class="c1"&gt;// 4) Enqueue many numbers for checking&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_prime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 5) Wait for all messages to be processed&lt;/span&gt;
    &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait_until_empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_prime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wait_until_empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count_prime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 6) Dispose the handlers&lt;/span&gt;
    &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;check_prime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;mm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count_prime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Print the total primes found&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Total primes in [1..100000]: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;prime_count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Highlights of &lt;code&gt;message_manager&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Handlers per Message ID&lt;/strong&gt;: Each &lt;code&gt;add_handler&lt;/code&gt; spawns an independent thread. If you want parallel processing for a single message ID, simply register multiple handlers for that ID.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordering Options&lt;/strong&gt;: By default, messages are queued in FIFO order, but you can choose FILO or RANDOM if needed for particular algorithms.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaner Synchronization&lt;/strong&gt;: &lt;code&gt;wait_until_empty(ID)&lt;/code&gt; ensures all tasks in that queue finish, letting you safely finalize results.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Feedback and Discussion
&lt;/h2&gt;

&lt;p&gt;Interested in trying Cbeam? We welcome feedback, ideas, and discussion on our &lt;a href="https://discord.gg/xHAAZbtwPQ" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt;. Whether you’re tackling concurrency challenges, bridging incompatible compilers, or simplifying shared memory usage, Cbeam aims to offer robust solutions under a permissive, modern C++ approach.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Check out &lt;a href="https://cbeam.org" rel="noopener noreferrer"&gt;Cbeam.org&lt;/a&gt; for detailed Doxygen docs, unit tests, and more examples to help streamline your next cross-platform C++ project.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>opensource</category>
      <category>concurrency</category>
      <category>serialization</category>
    </item>
    <item>
      <title>Ditana GNU/Linux: Unmatched Configuration Flexibility and Generic Hardware Detection</title>
      <dc:creator>Stefan Zipproth</dc:creator>
      <pubDate>Tue, 07 Jan 2025 15:21:23 +0000</pubDate>
      <link>https://dev.to/acrion/ditana-gnulinux-unmatched-configuration-flexibility-and-generic-hardware-detection-2g1f</link>
      <guid>https://dev.to/acrion/ditana-gnulinux-unmatched-configuration-flexibility-and-generic-hardware-detection-2g1f</guid>
      <description>&lt;p&gt;&lt;a href="https://ditana.org" rel="noopener noreferrer"&gt;Ditana GNU/Linux&lt;/a&gt; distinguishes itself from other distributions by providing a clean, JSON-driven configuration approach and a modern installer written in &lt;a href="https://ditana.org/docs/design-philosophy/why-raku" rel="noopener noreferrer"&gt;Raku&lt;/a&gt;. In this post, we’ll show you how Ditana uses JSON-based hardware detection and handles complex settings—such as the ZFS filesystem—through a concise, maintainable system that’s easy to extend. We’re also actively seeking developers and contributors who want to help shape Ditana’s future!&lt;/p&gt;

&lt;h3&gt;
  
  
  Hardware Detection in JSON
&lt;/h3&gt;

&lt;p&gt;Instead of scattering detection logic across multiple scripts, Ditana manages everything in JSON files. Each entry describes a specific hardware or system feature, along with the Raku code that runs at install time. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uefi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'/sys/firmware/efi'.IO.e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"required-by-chroot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"total-ram-gib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"('/proc/meminfo'.IO.lines.grep(/MemTotal/).first.words[1] / 1024 / 1024).ceiling"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"avx2-available"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'/proc/cpuinfo'.IO.lines.first(*.contains('flags')).contains('avx2').so"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;detect&lt;/code&gt; property contains Raku expressions that run at install time, making the logic straightforward and modular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced Configuration with &lt;code&gt;settings.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Beyond hardware detection, &lt;a href="https://github.com/acrion/ditana-installer/blob/main/airootfs/root/settings.json" rel="noopener noreferrer"&gt;settings.json&lt;/a&gt; also handles user-configurable options like filesystems or kernel selections. Here’s an example entry for ZFS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"zfs-filesystem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dialog-name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"File System"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"short-description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ZFS   - Snapshots, Self-Healing Storage &amp;amp; RAID-Z Support"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"long-description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ZFS: Supports atomic snapshots with a pre-configured snapshot solution instead of Timeshift. Designed for high data integrity with automatic self-healing. The installer will switch to the recommended Long-Term Support Kernel automatically, because ZFS requires DKMS modules (see Expert Settings → Kernel Selection menu available for selection later)."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"arch-packages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"zfs-utils"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spdx-identifiers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CDDL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"required-by-chroot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"available"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"`install-standard-lts-kernel OR install-standard-stable-kernel OR install-zen-kernel`"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"default-value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"`install-standard-lts-kernel`"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tristate
&lt;/h3&gt;

&lt;p&gt;Ditana utilizes a custom &lt;a href="https://github.com/acrion/ditana-installer/blob/main/airootfs/root/Tristate.rakumod" rel="noopener noreferrer"&gt;Tristate class&lt;/a&gt;—capable of True, False, and Any (undefined)—to manage values that are unknown or not yet defined. This flexibility is crucial for Ditana’s highly adaptable installer, which responds to both hardware attributes (like BIOS or UEFI, or drivers that may restrict kernel choice) and a wide range of user preferences.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tristate Logic Explained Through Its Unit Test
&lt;/h4&gt;

&lt;p&gt;In Raku, you can embed unit tests directly in the class, and they’ll run at compile time without requiring a dedicated test framework. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;CHECK&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Tristate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;True&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Tristate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;False&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Tristate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@tests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="nv"&gt;AND&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;False&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;False and Any&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="nv"&gt;AND&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;False&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Any and False&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt; &lt;span class="nv"&gt;AND&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(Any)&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;True and Any&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="nv"&gt;AND&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(Any)&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Any and True&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt; &lt;span class="nv"&gt;OR&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;True&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;  &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;True or Any&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="nv"&gt;OR&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;True&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt;  &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Any or True&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt; &lt;span class="nv"&gt;OR&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(Any)&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;False or Any&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="nv"&gt;OR&lt;/span&gt; &lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(Any)&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Any or False&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NOT&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(Any)&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not Any&lt;/span&gt;&lt;span class="p"&gt;'],&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NOT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="nv"&gt;OR&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="nv"&gt;OR&lt;/span&gt; &lt;span class="nv"&gt;$t&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;False&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not (Any or Any or True or Any)&lt;/span&gt;&lt;span class="p"&gt;']&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;@tests&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;Str&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nv"&gt;$expected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test '&lt;/span&gt;&lt;span class="si"&gt;$description&lt;/span&gt;&lt;span class="s2"&gt;' failed:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  Expected: &lt;/span&gt;&lt;span class="si"&gt;$expected&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  Got: &lt;/span&gt;&lt;span class="si"&gt;$result&lt;/span&gt;&lt;span class="s2"&gt;.Str()&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This demonstrates how Tristate gracefully handles undefined conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This is Relevant for Ditana
&lt;/h3&gt;

&lt;p&gt;Ditana’s flexible configuration possibilities require a way to resolve dependencies between settings. For example, with ZFS, the right boot manager (GRUB or ZFSBootMenu), kernel, and optional encryption settings all need to align. Things can get especially complex if you require special drivers or rely on a legacy BIOS. Thanks to this JSON-based configuration and the Tristate logic, Ditana ensures that any combination of user choices leads to a valid, bootable system. If something isn’t available, the installer won’t let you pick it—and it will explain why.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPU Vulnerability Mitigation Options
&lt;/h3&gt;

&lt;p&gt;In line with Ditana’s &lt;a href="https://ditana.org/docs/design-philosophy" rel="noopener noreferrer"&gt;design philosophy&lt;/a&gt;, our distribution enables CPU vulnerability mitigations in &lt;strong&gt;High Security Mode&lt;/strong&gt; by default. During installation, Ditana’s installer allows you to configure each detected CPU vulnerability individually, offering the option to maintain these enhanced security settings or revert to the &lt;a href="https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/index.html" rel="noopener noreferrer"&gt;default kernel configurations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default Kernel Settings vs. Ditana’s Mitigations&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The default kernel settings provided by the Linux kernel developers aim to balance security and performance. However, certain security vulnerabilities remain if you rely solely on these defaults. Ditana prioritises robust security by enabling mitigations that address these vulnerabilities via the &lt;a href="https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/index.html" rel="noopener noreferrer"&gt;officially documented kernel parameters&lt;/a&gt;. For most users, the performance implications of Ditana’s mitigations are negligible, while the security benefits are substantial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customization and Flexibility&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
We understand that some users may prefer to optimize their systems for maximum performance, even if it means accepting potential security trade-offs. Ditana’s installer framework therefore empowers you to adjust CPU vulnerability mitigation settings according to your preferences. Comprehensive explanations for each mitigation option are available through the installer’s Help button and detailed in the documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware-Specific Configuration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ditana's hardware detection system ensures that mitigation options are only presented for the specific vulnerabilities your CPU actually faces—and only for those where the Linux kernel itself does not use the maximum possible mitigation by default. For more details on which vulnerabilities are detected and which are not, see &lt;a href="https://ditana.org/docs/the-installer/kernel_configuration/mitigation" rel="noopener noreferrer"&gt;our documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By choosing Ditana’s default mitigation settings, you ensure that your system maintains a high level of security against known CPU vulnerabilities. We recommend keeping these settings enabled unless you have specific requirements that justify loosening them for performance considerations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"is-spectre-v2-vulnerable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"detect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"given '/sys/devices/system/cpu/vulnerabilities/spectre_v2'.IO { .e &amp;amp;&amp;amp; .slurp.chomp ne 'Not affected' }"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example from &lt;code&gt;settings.json&lt;/code&gt; to detect whether your CPU is vulnerable to Spectre V2.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Above: A preview of Ditana’s installation summary dialogue, showing the High Security Mitigations that would be configured in this example. You can decide to adopt Ditana’s mitigations or stick to the Linux kernel defaults.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic NVIDIA Driver Detection
&lt;/h3&gt;

&lt;p&gt;When it comes to NVIDIA graphics cards, Ditana employs a novel approach to identify whether a legacy driver is needed or if the current proprietary driver is more appropriate. During installation, the installer downloads and parses the official NVIDIA legacy GPU page at &lt;a href="https://www.nvidia.com/en-us/drivers/unix/legacy-gpu" rel="noopener noreferrer"&gt;https://www.nvidia.com/en-us/drivers/unix/legacy-gpu&lt;/a&gt;. If this page is unavailable or the parser requires updates (we run tests to validate the downloaded data), a cached and filtered version &lt;a href="https://github.com/acrion/ditana-installer/blob/main/airootfs/root/cached_legacy_gpu_page.html" rel="noopener noreferrer"&gt;from our repository&lt;/a&gt; is used instead. By comparing the detected GPU against the data in this page, the installer can determine if the user’s GPU necessitates a legacy driver. In cases where the required driver version is older than 470, the open-source Nouveau driver is recommended.  &lt;/p&gt;

&lt;p&gt;The default installation always uses the proprietary DKMS version of the NVIDIA driver, and the user can override the driver selection in the installer, for example to use the &lt;a href="https://github.com/NVIDIA/open-gpu-kernel-modules" rel="noopener noreferrer"&gt;NVIDIA open-source driver&lt;/a&gt;. However, impossible combinations are automatically disallowed. Ultimately, this system ensures that each NVIDIA card is matched with the safest and most compatible option available, while still preserving user choice where it makes sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Raku-Based Installer
&lt;/h3&gt;

&lt;p&gt;The Ditana installer is written in &lt;a href="https://ditana.org/docs/design-philosophy/why-raku" rel="noopener noreferrer"&gt;Raku&lt;/a&gt;, combining the succinct feel of shell scripting with modern error handling and concurrency features. Together with JSON-based detection and user-configurable settings, this approach keeps the code organized yet powerful—proving that advanced installation logic doesn’t require massive shell scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give Ditana a Spin!
&lt;/h3&gt;

&lt;p&gt;If you’re looking for an Arch-based distro that dares to think differently, Ditana might be your new best friend. From hardware detection to advanced filesystem setups, it even offers a local or cloud-based &lt;a href="https://ditana.org/assistant" rel="noopener noreferrer"&gt;AI assistant&lt;/a&gt; that can execute commands after confirmation (computer use). For ZFS, an optional &lt;a href="https://github.com/acrion/zfs-autosnap" rel="noopener noreferrer"&gt;auto-snapshot mechanism&lt;/a&gt; for easier maintenance is provided. Overall, currently there are 21 packages we developed for Ditana in its dedicated Arch repository (either mandatory or optional).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And if you’re interested in shaping Ditana’s future, we’d love your help!&lt;/strong&gt; Whether you’re a developer, documentation enthusiast, or just passionate about Linux, your contribution will be greatly appreciated. The project is split into multiple Arch packages, allowing you to pick the components you want. Plus, we have thorough documentation (both &lt;a href="https://github.com/acrion/ditana-installer/blob/main/airootfs/root/settings.json" rel="noopener noreferrer"&gt;inside the installer&lt;/a&gt; and &lt;a href="https://ditana.org/docs" rel="noopener noreferrer"&gt;on the website&lt;/a&gt;) so you’ll always understand the &lt;em&gt;why&lt;/em&gt; behind each setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions or Feedback?&lt;/strong&gt; You are welcome to drop a comment below! Ditana is constantly evolving, and we’re eager to hear your thoughts on improving our JSON-based detection, Tristate logic, or Raku-driven installer. We’re actively seeking collaborators who share our vision—come join us on this journey!&lt;/p&gt;

&lt;p&gt;Join the conversation on our dedicated &lt;a href="https://discord.gg/RgcdumdE9J" rel="noopener noreferrer"&gt;Ditana Discord Server&lt;/a&gt;, where we discuss features, share updates, and brainstorm ideas together.&lt;/p&gt;

</description>
      <category>security</category>
      <category>kernel</category>
      <category>zfs</category>
      <category>rakulang</category>
    </item>
  </channel>
</rss>
