Same address

Hey! I am a little confused on why does the connection object has the same memory address even though it goes out of the scope at the end of an iteration. I thought that we should have a fresh address for a connection object on each iteration

const std = @import("std");
const Thread = std.Thread;

fn handleNewConnection(connection: std.net.Server.Connection) !void {
    var buffer: [1000]u8 = undefined;

    while (try connection.stream.reader().read(&buffer) > 0) {
        _ = try connection.stream.write("+PONG\r\n");
    }

    connection.stream.close();
    _ = try std.io.getStdOut().writer().print("Connection closed", .{});
}

pub const TcpServer = struct {
    const Self = @This();

    pub fn bootstrap(host: []const u8, port: u16) !void {
        const address = try std.net.Address.resolveIp(host, port);

        var listener = try address.listen(.{
            .reuse_address = true,
        });
        defer listener.deinit();

        while (true) {
            const connection = try listener.accept();
            std.debug.print("Main thread connection addr: {*}\n", .{&connection});
            var thread = try Thread.spawn(.{}, handleNewConnection, .{connection});
            thread.detach();
        }
    }
};

Hello @vkondratiuk
Welcome to ziggit :slight_smile:

connection address is the same because it is reused.
The connection is allocated on stack; its life ends when the block ends } and it is freed.
In the next loop iteration, the stack pointer is restored and connection is allocated in the same stack address.

6 Likes

Yup, and that’s something to be careful of too.

If you were to hand that thread a &connection instead then every thread would be pointing to the latest connection and you would be leaking connections!

But inside your thread handling function, if you check the address, it would have its own copy of the connection struct. Which might be more what you’re interested in.