Replace shrink with shrinkAndFree and shrinkRetainingCapacity

This commit is contained in:
Zander Khan 2021-01-17 14:41:20 +00:00
parent e1ab425bce
commit 9a09ebb1b9
2 changed files with 100 additions and 6 deletions

View File

@ -382,9 +382,29 @@ pub fn PriorityDequeue(comptime T: type) type {
self.len = new_len;
}
pub fn shrink(self: *Self, new_len: usize) void {
// TODO take advantage of the new realloc semantics
assert(new_len <= self.len);
/// Reduce allocated capacity to `new_len`.
pub fn shrinkAndFree(self: *Self, new_len: usize) void {
assert(new_len <= self.items.len);
// Cannot shrink to smaller than the current queue size without invalidating the heap property
assert(new_len >= self.len);
self.items = self.allocator.realloc(self.items[0..], new_len) catch |e| switch (e) {
error.OutOfMemory => { // no problem, capacity is still correct then.
self.items.len = new_len;
return;
},
};
self.len = new_len;
}
/// Reduce length to `new_len`.
pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
assert(new_len <= self.items.len);
// Cannot shrink to smaller than the current queue size without invalidating the heap property
assert(new_len >= self.len);
self.len = new_len;
}
@ -798,6 +818,33 @@ test "std.PriorityDequeue: iterator while empty" {
expectEqual(it.next(), null);
}
test "std.PriorityDequeue: shrinkRetainingCapacity and shrinkAndFree" {
var queue = PDQ.init(testing.allocator, lessThanComparison);
defer queue.deinit();
try queue.ensureCapacity(4);
expect(queue.capacity() >= 4);
try queue.add(1);
try queue.add(2);
try queue.add(3);
expect(queue.capacity() >= 4);
expectEqual(@as(usize, 3), queue.len);
queue.shrinkRetainingCapacity(3);
expect(queue.capacity() >= 4);
expectEqual(@as(usize, 3), queue.len);
queue.shrinkAndFree(3);
expectEqual(@as(usize, 3), queue.capacity());
expectEqual(@as(usize, 3), queue.len);
expectEqual(@as(u32, 3), queue.removeMax());
expectEqual(@as(u32, 2), queue.removeMax());
expectEqual(@as(u32, 1), queue.removeMax());
expect(queue.removeMaxOrNull() == null);
}
test "std.PriorityDequeue: fuzz testing min" {
var prng = std.rand.DefaultPrng.init(0x12345678);

View File

@ -192,9 +192,29 @@ pub fn PriorityQueue(comptime T: type) type {
self.len = new_len;
}
pub fn shrink(self: *Self, new_len: usize) void {
// TODO take advantage of the new realloc semantics
assert(new_len <= self.len);
/// Reduce allocated capacity to `new_len`.
pub fn shrinkAndFree(self: *Self, new_len: usize) void {
assert(new_len <= self.items.len);
// Cannot shrink to smaller than the current queue size without invalidating the heap property
assert(new_len >= self.len);
self.items = self.allocator.realloc(self.items[0..], new_len) catch |e| switch (e) {
error.OutOfMemory => { // no problem, capacity is still correct then.
self.items.len = new_len;
return;
},
};
self.len = new_len;
}
/// Reduce length to `new_len`.
pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void {
assert(new_len <= self.items.len);
// Cannot shrink to smaller than the current queue size without invalidating the heap property
assert(new_len >= self.len);
self.len = new_len;
}
@ -477,6 +497,33 @@ test "std.PriorityQueue: iterator while empty" {
expectEqual(it.next(), null);
}
test "std.PriorityQueue: shrinkRetainingCapacity and shrinkAndFree" {
var queue = PQ.init(testing.allocator, lessThan);
defer queue.deinit();
try queue.ensureCapacity(4);
expect(queue.capacity() >= 4);
try queue.add(1);
try queue.add(2);
try queue.add(3);
expect(queue.capacity() >= 4);
expectEqual(@as(usize, 3), queue.len);
queue.shrinkRetainingCapacity(3);
expect(queue.capacity() >= 4);
expectEqual(@as(usize, 3), queue.len);
queue.shrinkAndFree(3);
expectEqual(@as(usize, 3), queue.capacity());
expectEqual(@as(usize, 3), queue.len);
expectEqual(@as(u32, 1), queue.remove());
expectEqual(@as(u32, 2), queue.remove());
expectEqual(@as(u32, 3), queue.remove());
expect(queue.removeOrNull() == null);
}
test "std.PriorityQueue: update min heap" {
var queue = PQ.init(testing.allocator, lessThan);
defer queue.deinit();