Declaring a buffer at comptime

Hi. It is late and all this is not very clear in my head, please forgive me if I’m not making sense.

I have a project where I build a computation graph at compile time. That graph is effectively a tree of nodes, and each of them may have an internal state if necessary.

For example, one node is a fixed length delay line: its internal state is a ring buffer where inputs are written to and outputs are read from.

This is fine, but I would like to have multiple nodes sharing a common buffer - for example, one node writes into the buffer, while others can read from it. How can I do that ??? Here is my first failed attempt.

const std = @import("std");

fn Writer(comptime buf: []f32) type {
    return struct {
        const Self = @This();

        buf: []f32 = buf,
        pos: usize = 0,

        fn write(self: *Self, value: f32) void {
            self.buf[self.pos] = value;
            self.pos = (self.pos + 1) % self.buf.len;
        }
    };
}

const buffer = [4]f32{ 0, 0, 0, 0 };

var w = Writer(@constCast(buffer[0..])){};

pub fn main() void {
    w.write(1);
    std.debug.print("{any}\n", .{buffer});
}

The buffer must live at runtime, cannot be a compile time argument.
You can create an init function that initializes buf with buffer.

    fn init(self: Self, buf: []f32) void {
        self.buf = buf;
    }
...
pub fn main() void {
    w.init(buffer);
    w.write(1);
    ...

Since there are no compiler time parameters, it is better to name the struct and create it using a function:

const Writer = struct {
    buf: []f32,
    pos: usize,

    fn create(buf: []f32) Writer {
        return .{
            .buf = buf,
            .pos = 0,
    }
    ...
};

...

pub fn main() void {
    var w = Writer.create(buffer);
    w.write(1);
    ...
}
1 Like