std1.0.0-beta-7 SafeC docs

Source dsp/timer_wheel.h

View in the repository

// SafeC Standard Library — Timer Wheel Scheduler
// Efficient O(1) timer management using a hashed timing wheel.
#pragma once
#include <std/erased.h>

#define WHEEL_SLOTS   256    // power-of-two number of buckets
#define WHEEL_TIMERS  64     // max timers (indices 0..WHEEL_TIMERS-1)

namespace std {

struct WheelTimer {
    unsigned long expires;   // absolute tick when the timer fires
    // One TimerWheel is a multi-tenant scheduler: its slots host timers
    // with unrelated context types at once, so each slot stores its
    // callback and context type-erased. They are only ever written by
    // TimerWheel::add/add_periodic below, which take a matching
    // fn void(?&T) / ?&T pair, so the erased call is always well-typed
    // (see std/erased.h).
    ?fn void(?&Erased) callback;  // the fn void(?&T); null when free
    ?&Erased           ctx;       // the ?&T
    int           used;      // 1 if slot occupied, 0 if free
    int           periodic;  // 1 → auto-reschedule every `period` ticks
    unsigned long period;    // interval for periodic timers
};

struct TimerWheel {
    struct WheelTimer timers[WHEEL_TIMERS];
    // slots[s] stores timer index+1 for the head of the list in bucket s,
    // 0 means the bucket is empty.  Chaining uses timers[id].ctx as next
    // pointer only conceptually; this implementation uses a flat scan for
    // simplicity and correctness within the WHEEL_TIMERS limit.
    unsigned long     current_tick;

    // Initialise the wheel in place to a clean state (all slots free,
    // tick = 0). Must be called before any other operation.
    void init();

    // One-shot timer calling cb(ctx) at absolute tick `tick`.
    // Returns the timer ID (1-based) or 0 if the wheel is full.
    generic<T> int add(unsigned long tick, fn void(?&T) cb, ?&T ctx);

    // Periodic timer calling cb(ctx) every `period` ticks, first at
    // current_tick + period. Returns the timer ID (1-based) or 0 if full.
    generic<T> int add_periodic(unsigned long period, fn void(?&T) cb, ?&T ctx);

    // Type-erased registration behind add/add_periodic.
    int  add_raw_(unsigned long tick, fn void(?&Erased) callback, ?&Erased ctx);
    int  add_periodic_raw_(unsigned long period, fn void(?&Erased) callback, ?&Erased ctx);

    // Cancel a timer by its ID.  Silently ignores invalid IDs.
    void cancel(int id);

    // Advance the wheel by one tick; fires all timers expiring at the new tick.
    // Periodic timers are automatically rescheduled.
    // Returns the number of timers fired.
    int  tick();

    // Return the current tick counter.
    unsigned long now() const;
};

generic<T>
int TimerWheel::add(unsigned long tick, fn void(?&T) cb, ?&T ctx) {
    unsafe { return self.add_raw_(tick, (fn void(?&Erased))cb, (?&Erased)ctx); }
}

generic<T>
int TimerWheel::add_periodic(unsigned long period, fn void(?&T) cb, ?&T ctx) {
    unsafe { return self.add_periodic_raw_(period, (fn void(?&Erased))cb, (?&Erased)ctx); }
}

} // namespace std