Skip to content

Instantly share code, notes, and snippets.

@jeremytregunna
Created December 3, 2024 15:12
Show Gist options
  • Save jeremytregunna/60d11ad8e9526122b7d0234b68492a6a to your computer and use it in GitHub Desktop.
Save jeremytregunna/60d11ad8e9526122b7d0234b68492a6a to your computer and use it in GitHub Desktop.
const std = @import("std");
const Timer = struct {
expiration: u64,
callback: *const fn () void,
};
const TimingWheel = struct {
buckets: [][]Timer,
current_time: u64,
bucket_size: u64,
num_buckets: usize,
allocator: *std.mem.Allocator,
pub fn init(allocator: *std.mem.Allocator, bucket_size: u64, num_buckets: usize) !*TimingWheel {
const wheel = try allocator.create(TimingWheel);
const buckets = try allocator.alloc([]Timer, num_buckets);
for (buckets) |*bucket| {
bucket.* = try allocator.alloc(Timer, 0);
}
wheel.* = TimingWheel{
.buckets = buckets,
.current_time = 0,
.bucket_size = bucket_size,
.num_buckets = num_buckets,
.allocator = allocator,
};
return wheel;
}
pub fn tick(self: *TimingWheel) !void {
self.current_time += 1;
const bucket_index = self.current_time % self.num_buckets;
const bucket = &self.buckets[bucket_index];
var i: usize = 0;
while (i < bucket.*.len) {
const timer = &bucket.*[i];
if (timer.expiration <= self.current_time) {
timer.callback();
// Remove the timer from the bucket
const last_index = bucket.*.len - 1;
if (i != last_index) {
bucket.*[i] = bucket.*[last_index];
}
bucket.* = try self.allocator.realloc(bucket.*, last_index);
} else {
i += 1;
}
}
}
pub fn addTimer(self: *TimingWheel, timer: Timer) !void {
const bucket_index = (timer.expiration / self.bucket_size) % self.num_buckets;
const bucket = &self.buckets[bucket_index];
// Check if the bucket is not initialized and initialize it
if (bucket.*.len == 0) {
bucket.* = try self.allocator.alloc(Timer, 1);
bucket.*[0] = timer;
} else {
// Make space to add the new timer
const new_len = bucket.*.len + 1;
bucket.* = try self.allocator.realloc(bucket.*, new_len);
bucket.*[new_len - 1] = timer;
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment