Skip to documentation
SLOP

tiny.game.settle

Reference tiny.game settle

Defined in tiny.game.

A detector that reports a change to a file once the file has held still for a window of time.

API (4)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callstiny.gamesettle
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: fun/game/src/root.zig:120

zig
pub const settle = @import("settle.zig");

Source: fun/game/src/settle.zig

zig
//! A detector that reports a change to a file once the file has held still for a window of time.//!//! A host that reloads code after a rebuild wants to act on each rebuild once, as soon as the new//! file is complete. A compiler writes a library file over a stretch of time, and the file's size//! can change more than once during one write, so a host that acts on the first change can load a//! half-written file.//!//! At each look the caller hands the detector the file's modification time and size at that look (a//! *stamp*) and the current time, so the detector reads no clock and no file of its own. A stamp//! that differs from the last one starts a window at the current time, and a later look with the//! same stamp at or past the window's end reports the change. A change seen while an earlier one//! waits starts the window again. The detector reports each change a single time, and then waits//! for the next change. The detector's first look records a baseline and reports nothing.const std = @import("std");/// A file's modification time and size, taken at one look. A caller builds one from each look at/// the file and passes it to `Settle.observe`.pub const Stamp = struct {    /// The file's modification time in nanoseconds, as the file system reports it.    mtime_ns: i128,    /// The file's size in bytes.    size: u64,    /// Returns true when both the modification time and the size match. `Settle.observe` tells with    /// it whether the file changed since the last look.    pub fn eql(a: Stamp, b: Stamp) bool {        return a.mtime_ns == b.mtime_ns and a.size == b.size;    }};/// The state of one change detector: the last stamp it saw and, while a change waits, the time at/// which it may report that change. A reloader keeps one for the file it watches and hands it a/// stamp at each poll. A detector starts empty, as `Settle{}`, and its first look records a/// baseline.pub const Settle = struct {    seen: ?Stamp = null,    fire_at: ?i128 = null,    /// Records one look at the file and returns true when a change has held still for `window_ns`    /// since the look that saw it. A caller looks at the file on its own schedule and acts on the    /// change when the call returns true. The first call records `stamp` as a baseline and returns    /// false. A stamp that differs from the last one is recorded, starts the window at `now_ns`,    /// and returns false. The same stamp returns false before the window's end and true at the    /// first look at or past it. After a true result, the call returns false until the stamp    /// changes again and a new window ends. The call reports only at a look, so a caller that looks    /// less often than the window hears of the change at its next look.    pub fn observe(self: *Settle, stamp: Stamp, now_ns: i128, window_ns: i128) bool {        const seen = self.seen orelse {            self.seen = stamp;            return false;        };        if (!seen.eql(stamp)) {            self.seen = stamp;            self.fire_at = now_ns + window_ns;            return false;        }        const deadline = self.fire_at orelse return false;        if (now_ns < deadline) return false;        self.fire_at = null;        return true;    }};const window: i128 = 100;test "the first observation is a baseline that never fires" {    var settle = Settle{};    try std.testing.expect(!settle.observe(.{ .mtime_ns = 5, .size = 10 }, 0, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 5, .size = 10 }, 1_000, window));}test "a settled change fires once after the window elapses" {    var settle = Settle{};    _ = settle.observe(.{ .mtime_ns = 5, .size = 10 }, 0, window);    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 12 }, 10, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 12 }, 50, window));    try std.testing.expect(settle.observe(.{ .mtime_ns = 6, .size = 12 }, 110, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 12 }, 200, window));}test "an unsettled file keeps re-arming and does not fire mid-write" {    var settle = Settle{};    _ = settle.observe(.{ .mtime_ns = 5, .size = 10 }, 0, window);    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 12 }, 10, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 40 }, 80, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 99 }, 130, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 6, .size = 99 }, 200, window));    try std.testing.expect(settle.observe(.{ .mtime_ns = 6, .size = 99 }, 240, window));}test "a second change after a fire arms again" {    var settle = Settle{};    _ = settle.observe(.{ .mtime_ns = 5, .size = 10 }, 0, window);    _ = settle.observe(.{ .mtime_ns = 6, .size = 12 }, 10, window);    try std.testing.expect(settle.observe(.{ .mtime_ns = 6, .size = 12 }, 120, window));    try std.testing.expect(!settle.observe(.{ .mtime_ns = 7, .size = 14 }, 130, window));    try std.testing.expect(settle.observe(.{ .mtime_ns = 7, .size = 14 }, 240, window));}

Audit

Definitions5
Public names5
Members4
Version26.7.0
Revisiondaab053ee433