| ... | ... | @@ -139,22 +139,23 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type |
| 139 | 139 | |
| 140 | 140 | pub fn addOne(self: &Self) !&T { |
| 141 | 141 | const new_length = self.len + 1; |
| 142 | | try self.setCapacity(new_length); |
| 142 | try self.growCapacity(new_length); |
| 143 | 143 | const result = self.uncheckedAt(self.len); |
| 144 | 144 | self.len = new_length; |
| 145 | 145 | return result; |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | /// Grows or shrinks capacity to match usage. |
| 148 | 149 | pub fn setCapacity(self: &Self, new_capacity: usize) !void { |
| 149 | | if (new_capacity <= prealloc_item_count) { |
| 150 | | const len = ShelfIndex(self.dynamic_segments.len); |
| 151 | | if (len == 0) return; |
| 152 | | self.freeShelves(len, 0); |
| 153 | | self.allocator.free(self.dynamic_segments); |
| 154 | | self.dynamic_segments = []&T{}; |
| 155 | | return; |
| 150 | if (new_capacity <= usize(1) << (prealloc_exp + self.dynamic_segments.len)) { |
| 151 | return self.shrinkCapacity(new_capacity); |
| 152 | } else { |
| 153 | return self.growCapacity(new_capacity); |
| 156 | 154 | } |
| 155 | } |
| 157 | 156 | |
| 157 | /// Only grows capacity, or retains current capacity |
| 158 | pub fn growCapacity(self: &Self, new_capacity: usize) !void { |
| 158 | 159 | const new_cap_shelf_count = shelfCount(new_capacity); |
| 159 | 160 | const old_shelf_count = ShelfIndex(self.dynamic_segments.len); |
| 160 | 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 | 168 | while (i < new_cap_shelf_count) : (i += 1) { |
| 168 | 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 | 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 | 187 | if (new_cap_shelf_count == old_shelf_count) { |
| 173 | 188 | return; |
| 174 | 189 | } |
| 190 | |
| 175 | 191 | self.freeShelves(old_shelf_count, new_cap_shelf_count); |
| 176 | 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 | 195 | pub fn uncheckedAt(self: &Self, index: usize) &T { |
| 185 | 196 | if (index < prealloc_item_count) { |
| 186 | 197 | return &self.prealloc_segment[index]; |