| ... | @@ -139,22 +139,23 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type | ... | @@ -139,22 +139,23 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 139 | | 139 | |
| 140 | pub fn addOne(self: &Self) !&T { | 140 | pub fn addOne(self: &Self) !&T { |
| 141 | const new_length = self.len + 1; | 141 | const new_length = self.len + 1; |
| 142 | try self.setCapacity(new_length); | 142 | try self.growCapacity(new_length); |
| 143 | const result = self.uncheckedAt(self.len); | 143 | const result = self.uncheckedAt(self.len); |
| 144 | self.len = new_length; | 144 | self.len = new_length; |
| 145 | return result; | 145 | return result; |
| 146 | } | 146 | } |
| 147 | | 147 | |
| | 148 | /// Grows or shrinks capacity to match usage. |
| 148 | pub fn setCapacity(self: &Self, new_capacity: usize) !void { | 149 | pub fn setCapacity(self: &Self, new_capacity: usize) !void { |
| 149 | if (new_capacity <= prealloc_item_count) { | 150 | if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) { |
| 150 | const len = ShelfIndex(self.dynamic_segments.len); | 151 | return self.shrinkCapacity(new_capacity); |
| 151 | if (len == 0) return; | 152 | } else { |
| 152 | self.freeShelves(len, 0); | 153 | return self.growCapacity(new_capacity); |
| 153 | self.allocator.free(self.dynamic_segments); | | |
| 154 | self.dynamic_segments = []&T{}; | | |
| 155 | return; | | |
| 156 | } | 154 | } |
| | 155 | } |
| 157 | | 156 | |
| | 157 | /// Only grows capacity, or retains current capacity |
| | 158 | pub fn growCapacity(self: &Self, new_capacity: usize) !void { |
| 158 | const new_cap_shelf_count = shelfCount(new_capacity); | 159 | const new_cap_shelf_count = shelfCount(new_capacity); |
| 159 | const old_shelf_count = ShelfIndex(self.dynamic_segments.len); | 160 | const old_shelf_count = ShelfIndex(self.dynamic_segments.len); |
| 160 | if (new_cap_shelf_count > old_shelf_count) { | 161 | if (new_cap_shelf_count > old_shelf_count) { |
| ... | @@ -167,20 +168,30 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type | ... | @@ -167,20 +168,30 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 167 | while (i < new_cap_shelf_count) : (i += 1) { | 168 | while (i < new_cap_shelf_count) : (i += 1) { |
| 168 | self.dynamic_segments[i] = (try self.allocator.alloc(T, shelfSize(i))).ptr; | 169 | self.dynamic_segments[i] = (try self.allocator.alloc(T, shelfSize(i))).ptr; |
| 169 | } | 170 | } |
| | 171 | } |
| | 172 | } |
| | 173 | |
| | 174 | /// Only shrinks capacity or retains current capacity |
| | 175 | pub fn shrinkCapacity(self: &Self, new_capacity: usize) void { |
| | 176 | if (new_capacity <= prealloc_item_count) { |
| | 177 | const len = ShelfIndex(self.dynamic_segments.len); |
| | 178 | self.freeShelves(len, 0); |
| | 179 | self.allocator.free(self.dynamic_segments); |
| | 180 | self.dynamic_segments = []&T{}; |
| 170 | return; | 181 | return; |
| 171 | } | 182 | } |
| | 183 | |
| | 184 | const new_cap_shelf_count = shelfCount(new_capacity); |
| | 185 | const old_shelf_count = ShelfIndex(self.dynamic_segments.len); |
| | 186 | assert(new_cap_shelf_count <= old_shelf_count); |
| 172 | if (new_cap_shelf_count == old_shelf_count) { | 187 | if (new_cap_shelf_count == old_shelf_count) { |
| 173 | return; | 188 | return; |
| 174 | } | 189 | } |
| | 190 | |
| 175 | self.freeShelves(old_shelf_count, new_cap_shelf_count); | 191 | self.freeShelves(old_shelf_count, new_cap_shelf_count); |
| 176 | self.dynamic_segments = self.allocator.shrink(&T, self.dynamic_segments, new_cap_shelf_count); | 192 | self.dynamic_segments = self.allocator.shrink(&T, self.dynamic_segments, new_cap_shelf_count); |
| 177 | } | 193 | } |
| 178 | | 194 | |
| 179 | pub fn shrinkCapacity(self: &Self, new_capacity: usize) void { | | |
| 180 | assert(new_capacity <= prealloc_item_count or shelfCount(new_capacity) <= self.dynamic_segments.len); | | |
| 181 | self.setCapacity(new_capacity) catch unreachable; | | |
| 182 | } | | |
| 183 | | | |
| 184 | pub fn uncheckedAt(self: &Self, index: usize) &T { | 195 | pub fn uncheckedAt(self: &Self, index: usize) &T { |
| 185 | if (index < prealloc_item_count) { | 196 | if (index < prealloc_item_count) { |
| 186 | return &self.prealloc_segment[index]; | 197 | return &self.prealloc_segment[index]; |