Xeon Productions

Introducing Stainless

I've been working on something for a while now that I haven't really talked about here, so it's about time. It's called Stainless, and it's a programming language.

The short version is that it's C#'s syntax on top of C's memory model. It compiles to native code through LLVM, lays out its types exactly like C does, and can call into C (or be called from it) with no wrapper layer in between. Instead of a garbage collector it uses reference counting, so objects are cleaned up the moment nothing points at them anymore. And there are no header files: the compiler reads the whole program up front, so you declare something once and use it anywhere.

If you know C#, most of this should look familiar:

module Points;

import Standard.Console;

record Point(int X, int Y);

String Describe(Point p) => p switch
{
    (0, 0) => "the origin",
    { X: 0 } => "on the Y axis",
    (var x, var y) when x == y => "on the diagonal",
    _ => $"somewhere else ({p.X}, {p.Y})"
};

int Main()
{
    Point[] points = [new(0, 0), new(0, 5), new(3, 3), new(4, 1)];
    foreach (var p in points)
        Console.WriteLine(Describe(p));
    return 0;
}

Records, pattern matching, collection expressions, target-typed new, generics, lambdas and properties are all there. A few things are different on purpose: there are no exceptions (errors are Result values instead), there's no async/await (it has parallel and spawn), and lambdas capture by value.

The part I'm proudest of is that it's built out of itself. The standard library, a GUI framework with Win32 and GTK back ends, and an IDE with a form designer and a debugger are all written in Stainless. If the language couldn't handle a real program, I'd have found out pretty quickly.

It's still experimental, it's still changing, and it's just me working on it, so don't go shipping anything important with it yet. That said, there are builds for Windows and Linux on the releases page if you want to try it. You'll need clang installed, and the README walks you through the rest.

Everything's up on GitHub: github.com/xeons/stainless

If you give it a try, I'd love to hear what you think.

New website and new host

I've been talking about rewriting this site since at least 2019, and I finally got around to it. What you're looking at is no longer WordPress; it's a .NET 10 Blazor application I wrote from scratch, sitting on Postgres, running in Docker behind nginx. I said back then that I might redo it in Laravel if I ever found the motivation, but I write C# all day at work, so Blazor made a lot more sense than writing in PHP.

I also moved the site to a more powerful VPS over at OVH, which gives me a lot more wiggle room to run Minecraft servers and whatever else I feel like hosting.

There's a new developer tools section as well, and a light and dark theme selector. I also built the traffic stats directly into the site instead of relying on Google Analytics.

I'm going to try to write some new tutorials and put up some better snippets. Anyway, hopefully this isn't my only post this year and I can get some more updates out.

Upgraded to a new host

I decided to look around for a more affordable VPS providers with better specs for the money, and found Hetzner. Now I’ve gone from a 2 core, 2 GB, 40 GB instance to a 4 core, 8 GB, 160 GB server for a little more than I’m paying now at DigitalOcean. I’m hoping this new service won’t let me down. I was also kind of disappointed with DigitalOcean, they don’t have the type of droplet I originally had for $12.

In other news I’ve been doing a little bit more web development in my spare time, so that motivated me to possibly start working on my personal website again. I’ve also finally started looking into container technology like docker. I’m not sure what I want to containerize, but I’m sure I’ll find a project.

Obligatory I’m Still Alive post

It’s almost a running joke at this point, but I’m still alive! COVID hasn’t killed me yet, and we haven’t been plunged into a nuclear winter; so yay!

I have no idea what I’m doing with this site, other than keeping it up as beacon of hope that I may one day find the motivation and willpower to upload some monumental project that will change the world. I did upgrade the server to the latest LTS release of Ubuntu, as well as the latest version of WordPress. I’m hoping I can at least update some things, and post some new content; but as you know I’ve made that promise many times over the past 15 years. I can’t say it’s for the lack of time, because I have plenty of time after work.

Anyway, I hope everyone else is doing great, and if you’re still checking up on this site from time to time I thank you.

.NET Socket *Async methods have a design flaw.

So I was attempting to make use of IO completion ports and build a high performance socket server in C# by making use of the *Async methods such as ReceiveAsync with SocketAsyncEventArgs. However I’ve encountered a problem which I cannot seem to find a solution for which involves a StackOverException being triggered by the execution of these methods. You see, at first glance everything appeared to be humming along nicely, until I decided to flood my server with about 12,000 randomly sized packets. That’s when the problem shows up.

I have a TryReceive method that makes the first call to ReceiveAsync, and if it returns FALSE, then I call the ProcessReceive directly, otherwise it gets called by the Completed event getting invoked on the SocketAsyncEventArgs. ProcessReceive then does some processing of the message and then calls TryReceive to start the process all over again. For whatever reason, the ReceiveAsync is always completing synchronously and creating a recursive loop with my two methods.

I’m not really sure what to try at this point, other than possibly trying to call it on another thread, but I’m worried that might cause some other recursive thread call issues. If anyone has any ideas feel free to hit up my contact form.

Here’s some extracted snippets of code to show how the calls are structured.

private void TryReceive()
{
...
    if (!Socket.ReceiveAsync(_receiveEventArg))
        ProcessReceive(_receiveEventArg);
...
}

private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)
{
    // Determine which type of operation just completed and call the associated handler
    switch (e.LastOperation)
    {
        case SocketAsyncOperation.Receive:
            ProcessReceive(e);
            break;
        case SocketAsyncOperation.Send:
            ProcessSend(e);
            break;
        default:
            throw new ArgumentException("The last operation completed on the socket was not a receive or send");
    }

}

private void ProcessReceive(SocketAsyncEventArgs e)
{
...
    if (e.SocketError == SocketError.Success)
    {
        // If zero is returned from a read operation, the remote end has closed the connection
        if (size > 0)
            TryReceive();
        else
            Disconnect();
        }
    }
...
}