Zig NEWS

Cover image for Cool Zig Patterns - Stable Main Loop
Felix "xq" Queißner
Felix "xq" Queißner

Posted on • Updated on

Cool Zig Patterns - Stable Main Loop

This pattern was designed while working on a init system which has as the critical requirement to never crash or exit, no matter what happens.

But usually you need to set up some stuff before going into the main loop. The simple, but (to me) not so obvious solution was this:

pub fn main() !u8 {
  // setup phase, load all data here

  var data = try loadData();
  defer data.deinit();

  log.info("ready.", .{});
  coreLoop(&data);
  log.info("clean application exit.", .{});

  // teardown phase, clean up your resources here!

  return 0;
}

fn coreLoop(data: *Data) void {
  while(true) {
    // Do your application logic here!
  }
}
Enter fullscreen mode Exit fullscreen mode

By splitting main() into a setup phase, coreLoop() and teardown phase, we can put the guarantee to not error at runtime into the function contract of coreLoop().

coreLoop() can't return an error, so we're never able to leave the function unexpectedly and it will be a compile error to do so.

This makes reviewing the code much easier as well.

Latest comments (1)

Collapse
 
kristoff profile image
Loris Cro

Nice! This is the same design idea behind std.event.Loop.runDetached: since the async function will not have a surrounding context capable of handling errors, the function you pass in as an argument is required to return void.

github.com/ziglang/zig/blob/master...

/// Runs the provided function asynchronously. The function's frame is allocated
/// with `allocator` and freed when the function returns.
/// `func` must return void and it can be an async function.
/// Yields to the event loop, running the function on the next tick.
pub fn runDetached(self: *Loop, alloc: mem.Allocator, comptime func: anytype, args: anytype) error{OutOfMemory}!void {
   if (!std.io.is_async) @compileError("Can't use runDetached in non-async mode!");
   if (@TypeOf(@call(.{}, func, args)) != void) {
       @compileError("`func` must not have a return value");
    }
   // ...
}
Enter fullscreen mode Exit fullscreen mode