| ... | @@ -12,6 +12,8 @@ const testing = std.testing; | ... | @@ -12,6 +12,8 @@ const testing = std.testing; |
| 12 | pub fn FixedSizeFifo(comptime T: type) type { | 12 | pub fn FixedSizeFifo(comptime T: type) type { |
| 13 | const autoalign = false; | 13 | const autoalign = false; |
| 14 | | 14 | |
| | 15 | const powers_of_two = true; |
| | 16 | |
| 15 | return struct { | 17 | return struct { |
| 16 | allocator: *Allocator, | 18 | allocator: *Allocator, |
| 17 | buf: []T, | 19 | buf: []T, |
| ... | @@ -68,10 +70,10 @@ pub fn FixedSizeFifo(comptime T: type) type { | ... | @@ -68,10 +70,10 @@ pub fn FixedSizeFifo(comptime T: type) type { |
| 68 | } | 70 | } |
| 69 | | 71 | |
| 70 | /// Ensure that the buffer can fit at least `size` items | 72 | /// Ensure that the buffer can fit at least `size` items |
| 71 | pub fn ensureCapacity(self: *Self, size: usize) error{OutOfMemory}!void { | 73 | pub fn ensureCapacity(self: *Self, size: usize) !void { |
| 72 | if (self.buf.len >= size) return; | 74 | if (self.buf.len >= size) return; |
| 73 | self.realign(); | 75 | self.realign(); |
| 74 | const new_size = math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory; | 76 | const new_size = if (powers_of_two) math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory else size; |
| 75 | self.buf = try self.allocator.realloc(self.buf, new_size); | 77 | self.buf = try self.allocator.realloc(self.buf, new_size); |
| 76 | } | 78 | } |
| 77 | | 79 | |
| ... | @@ -124,10 +126,19 @@ pub fn FixedSizeFifo(comptime T: type) type { | ... | @@ -124,10 +126,19 @@ pub fn FixedSizeFifo(comptime T: type) type { |
| 124 | @memset(unused2.ptr, undefined, unused2.len); | 126 | @memset(unused2.ptr, undefined, unused2.len); |
| 125 | } | 127 | } |
| 126 | } | 128 | } |
| 127 | self.head = (self.head + count) % self.buf.len; | 129 | if (autoalign and self.count == count) { |
| 128 | self.count -= count; | | |
| 129 | if (autoalign and self.count == 0) | | |
| 130 | self.head = 0; | 130 | self.head = 0; |
| | 131 | self.count = 0; |
| | 132 | } else { |
| | 133 | var head = self.head + count; |
| | 134 | if (powers_of_two) { |
| | 135 | head &= self.buf.len - 1; |
| | 136 | } else { |
| | 137 | head %= self.buf.len; |
| | 138 | } |
| | 139 | self.head = head; |
| | 140 | self.count -= count; |
| | 141 | } |
| 131 | } | 142 | } |
| 132 | | 143 | |
| 133 | /// Read the next item from the fifo | 144 | /// Read the next item from the fifo |
| ... | @@ -225,7 +236,13 @@ pub fn FixedSizeFifo(comptime T: type) type { | ... | @@ -225,7 +236,13 @@ pub fn FixedSizeFifo(comptime T: type) type { |
| 225 | fn rewind(self: *Self, size: usize) void { | 236 | fn rewind(self: *Self, size: usize) void { |
| 226 | assert(self.writableLength() >= size); | 237 | assert(self.writableLength() >= size); |
| 227 | | 238 | |
| 228 | self.head = (self.head + (self.buf.len - size)) % self.buf.len; | 239 | var head = self.head + (self.buf.len - size); |
| | 240 | if (powers_of_two) { |
| | 241 | head &= self.buf.len - 1; |
| | 242 | } else { |
| | 243 | head %= self.buf.len; |
| | 244 | } |
| | 245 | self.head = head; |
| 229 | self.count += size; | 246 | self.count += size; |
| 230 | } | 247 | } |
| 231 | | 248 | |
| ... | @@ -246,7 +263,13 @@ pub fn FixedSizeFifo(comptime T: type) type { | ... | @@ -246,7 +263,13 @@ pub fn FixedSizeFifo(comptime T: type) type { |
| 246 | if (offset >= self.count) | 263 | if (offset >= self.count) |
| 247 | return error.EndOfStream; | 264 | return error.EndOfStream; |
| 248 | | 265 | |
| 249 | return self.buf[(self.head + offset) % self.buf.len]; | 266 | var index = self.head + offset; |
| | 267 | if (powers_of_two) { |
| | 268 | index &= self.buf.len - 1; |
| | 269 | } else { |
| | 270 | index %= self.buf.len; |
| | 271 | } |
| | 272 | return self.buf[index]; |
| 250 | } | 273 | } |
| 251 | }; | 274 | }; |
| 252 | } | 275 | } |