authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-07 10:34:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-07 10:34:38-04:00
log2f633452bb337a3f173c4fd82c2b4a0880f981f5
treef038a1e55dd4f11df01dee7d504841e728baf5c6
parent78ba3b84850c1e1494797f76d147bc8c87f749e1

std.SegmentedList: cleaner separation of capacity functions


1 files changed, 24 insertions(+), 13 deletions(-)

std/segmented_list.zig+24-13
...@@ -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
139139
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 }
147147
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 }
157156
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 }
178194
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];