Created
January 8, 2020 16:08
-
-
Save travisstaloch/6235b1fb73c2d16e120848d7c8449b3a to your computer and use it in GitHub Desktop.
A simple ring buffer inspired by https://github.com/tsoding/nothing/blob/master/src/ring_buffer.c
This file contains 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"); | |
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