Skip to content

Instantly share code, notes, and snippets.

@travisstaloch
Created January 8, 2020 16:08
Show Gist options
  • Save travisstaloch/6235b1fb73c2d16e120848d7c8449b3a to your computer and use it in GitHub Desktop.
Save travisstaloch/6235b1fb73c2d16e120848d7c8449b3a to your computer and use it in GitHub Desktop.
const std = @import("std");
pub fn RingBuffer(comptime T: type) type {
return struct {
data: []T,
current: [*]T,
count: usize,
dtor: ?fn (T) void,
const Self = @This();
pub fn init(data: []T, dtor: ?fn (T) void) Self {
return .{ .data = data, .current = data.ptr, .count = 0, .dtor = dtor };
}
/// calls dtor() on overwritten element when full
pub fn push(self: *Self, element: T) void {
self.current.* = element;
self.current += 1;
if (self.count >= self.data.len) {
if (self.dtor) |dtor| dtor(self.current[0]);
} else self.count = (self.count + 1) % (self.data.len + 1);
if (@ptrToInt(self.current) >= @ptrToInt(self.data.ptr + self.data.len))
self.current = self.data.ptr;
}
pub fn pop(self: *Self) ?T {
if (self.count == 0) return null;
self.count -= 1;
self.current -= 1;
if (@ptrToInt(self.current) < @ptrToInt(self.data.ptr))
self.current = self.data.ptr + self.data.len - 1;
return self.current[0];
}
pub fn top(self: Self) ?T {
if (self.count == 0) return null;
const current = (if (self.current == self.data.ptr)
self.data.ptr + self.data.len
else
self.current) - 1;
return current[0];
}
};
}
test "basic" {
const assert = std.debug.assert;
var data = [_]u32{0} ** 5;
var ring = RingBuffer(u32).init(&data, null);
var i: u32 = 1;
assert(ring.pop() == null);
assert(ring.top() == null);
while (i < 8) : (i += 1)
ring.push(i);
// for (ring.data) |e| std.debug.warn("{}, ", .{e});
// std.debug.warn("\n", .{});
assert(ring.data[0] == 6 and ring.data[4] == 5 and ring.top().? == 7);
i = 1;
while (i < 5) : (i += 1) {
const x = ring.pop();
// std.debug.warn("x={}, top={}\n", .{ x, ring.top() });
}
// for (ring.data) |e| std.debug.warn("{}, ", .{e});
// std.debug.warn("\n", .{});
assert(ring.top().? == 3);
i = 1;
while (i < 7) : (i += 1)
ring.push(i);
// for (ring.data) |e| std.debug.warn("{}, ", .{e});
// std.debug.warn("\n", .{});
assert(ring.data[0] == 3 and ring.data[4] == 2 and ring.top().? == 6);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment