std.time.Timer got removed, what are the plans for it if any?

I was using it one of my projects, and just noticed it’s gone. I tried searching about it but was not able to find much so I’m asking here.

1 Like

It’s trivial to implement, I don’t see why it existed in the first place.

zigs time API is getting an overhaul with Io, you now have more control over what clock to use. Even with the removal of Timer I would say the API has generally more convenience.

You’ll find every thing, except the unit conversion amounts, under std.Io now. Perhaps that will change in the future IDK.

1 Like

Yes, everything that I need is under Timestamp now and having a clock to choose from , I like.

1 Like

I’ve asked a very similar question to this here!

I ended up doing this to count the time :))

const start = Io.Clock.real.now(init.io);
_ = doSomeWork();
const end = Io.Clock.real.now(init.io);

const duration = std.Io.Timestamp.durationTo(start, end); 
try stdout.print("Time Elapsed: {d} ms\n", .{duration.toMilliseconds()});

I find annoying that there isn’t (or I have not seen ofc) a function in Timestamp to return the seconds as a float (eg, 3.334 s) but it can be easily done!

1 Like

You can use conversion from std.time. I’ll show larger snippets so you can have more context.
Getting initial timestamp:

    // Timer for switching logic and syncing threads. If time exceeds duration (specified in sec), switch endpoints.
    // Block switcihing on every packet sent from server to client
    var timer: ?std.Io.Clock.Timestamp = null;
    const time: ?usize = config.switcher.timer;
    var switcher_thread: ?std.Thread = null;
    var packet_arrived = true;

    // Comply with the switcher flag
    if (config.switcher.enabled) if (time) |seconds| {
        std.log.info("Spawning switcher thread....", .{});
        timer = std.Io.Clock.Timestamp.now(io, .awake);
        switcher_thread = try std.Thread.spawn(.{}, switcher, .{
            io,
            seconds,
            &timer,
            servers,
            &current_id,
            &packet_arrived,
        });
    } else {
        std.log.debug("Switcher enabled but timer interval value is: {any}", .{time});
        return error.FailedToUnwrap;
    } else {
        std.log.info("Switching disabled, using endpoint derived form ID....", .{});
    }

And my switcher thread where I do a reset and duration check:

fn switcher(
    io: std.Io,
    seconds: usize,
    timer: *?std.Io.Clock.Timestamp,
    servers: []std.Io.net.IpAddress,
    current_id: *usize,
    packet_arrived: *bool,
) !void {
    // Unwrap timer  optional
    if (timer.*) |*t| {
        // Declare constants once before the main loop
        const duration: u64 = std.time.ns_per_s * seconds;

        while (true) {
            const elapsed = t.untilNow(io).raw.nanoseconds;
            std.log.debug("Timer time elapsed: {d}", .{elapsed});
            std.log.debug("Timer time duration: {d}", .{duration});
            std.log.debug("Timer packet_arrived state: {}", .{packet_arrived.*});

            // Main check is if packet has arrived
            if (!packet_arrived.*) {
                // Second check is if enough time has passsed before switching
                if (elapsed < duration) {
                    try io.sleep(.fromNanoseconds(duration - elapsed), .awake);
                    continue;
                }
                const new_id = (current_id.* + 1) % servers.len;
                current_id.* = new_id;
                std.log.info("Switched servers endpoints!", .{});
                std.log.info("Current endpoint: {f}", .{&servers[current_id.*]});
                // Reset packet state
                packet_arrived.* = true;
            }
            // Reset timer to sync threads
            t.* = std.Io.Clock.Timestamp.now(io, .awake);
            try io.sleep(.fromNanoseconds(duration), .awake);
        }
    } else {
        std.log.err("Switcher got called but timer variable value is: {any}", .{timer});
        return error.FailedToUnwrap;
    }
}

In case you want to see more code, it’s from this tool I wrote:

For some reason I still hesitate to make an official showcase for it :smiley:

1 Like

FWIW you can rewrite this to:

const duration = start.durationTo(end);

…in my own code, I use this for elapsed time (where Timestamp has been imported as const Timestamp = std.Io.Timestamp;:

const startTime = Timestamp.now(io, .real);
// ...
const elapsedTime = startTime.untilNow(io, .real);
12 Likes

RIP Timer :smiling_face_with_tear: . I thought it was a nice quick to understand bundle of functionality. Sad to see it go.

2 Likes

I recently replaced time.Timer in zbench ( GitHub - hendriknielaender/zBench: 📊 zig benchmark · GitHub ), the new “timer” is basically just

const t0 = Timestamp.now(io, .awake);
// do stuff synchronously
const t1_ns = t0.untilNow(io, .awake).toNanoseconds(); 

This appears plain and simple, no unnecessary abstraction. Even better, the new variant lets me choose a clock. Great work @ zig-contributors! And @floooh for highlighting this functionality here.

6 Likes

I was wondering how you toNanoseconds() function, and the difference is that I was using std.Io.Clock.Timestamp and you were using std.Io.Timestamp.

Yes, this is a bit confusing, that there are two kind of Timestamps. You should be able to use std.Io.Clock.Timestamp.raw to get the std.Io.Timestamp though.

1 Like

just use event-driven-state-machines, like this