Created
December 3, 2024 15:12
-
-
Save jeremytregunna/60d11ad8e9526122b7d0234b68492a6a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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