@@ -64,35 +64,33 @@ pub fn SegmentList(Segment: type) type {
64
64
}
65
65
66
66
pub fn appendSegmentInto (self : Self , copy : * Self , node : Node ) void {
67
+ copy .nodes .clearRetainingCapacity ();
67
68
for (self .nodes .items ) | n | {
68
69
copy .nodes .appendAssumeCapacity (n .acquire ());
69
70
}
70
71
copy .nodes .appendAssumeCapacity (node .acquire ());
71
72
}
72
73
73
- pub fn appendSegment (self : * Self , allocator : Allocator , node : Node ) Allocator.Error ! Self {
74
- var copy = try Self .init (allocator , self .nodes .items .len + 1 );
75
- self .appendSegmentInto (& copy , node );
76
- return copy ;
77
- }
78
-
79
- pub fn removeSegment (self : * Self , allocator : Allocator , idx : usize ) Allocator.Error ! Self {
80
- var copy = try Self .init (allocator , self .nodes .items .len - 1 );
81
- for (self .nodes .items , 0.. ) | n , i | {
82
- if (i != idx ) {
74
+ pub fn removeSegmentInto (self : Self , copy : * Self , node : Node ) void {
75
+ copy .nodes .clearRetainingCapacity ();
76
+ for (self .nodes .items ) | n | {
77
+ if (n .value != node .value ) {
83
78
copy .nodes .appendAssumeCapacity (n .acquire ());
84
79
}
85
80
}
86
- return copy ;
87
81
}
88
82
89
- pub fn replaceSegments (self : * Self , allocator : Allocator , node : Node , start_idx : usize , end_idx : usize ) Allocator.Error ! Self {
90
- var copy = try Self .init (allocator , self .nodes .items .len + 1 - (end_idx - start_idx ));
91
- for (self .nodes .items , 0.. ) | n , i | {
92
- if (i < start_idx or i >= end_idx ) {
83
+ pub fn replaceMergedSegmentInto (self : * Self , copy : * Self , node : Node ) Self {
84
+ copy .nodes .clearRetainingCapacity ();
85
+ var inserted_merged = false ;
86
+ for (self .nodes .items ) | n | {
87
+ if (node .value .id .contains (n .value .id )) {
88
+ if (! inserted_merged ) {
89
+ copy .nodes .appendAssumeCapacity (node );
90
+ inserted_merged = true ;
91
+ }
92
+ } else {
93
93
copy .nodes .appendAssumeCapacity (n .acquire ());
94
- } else if (i == start_idx ) {
95
- copy .nodes .appendAssumeCapacity (node .acquire ());
96
94
}
97
95
}
98
96
return copy ;
@@ -232,8 +230,8 @@ pub fn SegmentListManager(Segment: type) type {
232
230
233
231
const candidate = self .merge_policy .findSegmentsToMerge (segments .value .nodes .items ) orelse return false ;
234
232
235
- var target = try List .createSegment (self .allocator , self .options );
236
- errdefer List .destroySegment (self .allocator , & target );
233
+ var new_segment = try List .createSegment (self .allocator , self .options );
234
+ defer List .destroySegment (self .allocator , & new_segment );
237
235
238
236
var merger = SegmentMerger (Segment ).init (self .allocator , segments .value );
239
237
defer merger .deinit ();
@@ -243,64 +241,73 @@ pub fn SegmentListManager(Segment: type) type {
243
241
}
244
242
try merger .prepare ();
245
243
246
- try target .value .merge (& merger );
247
- errdefer target .value .cleanup ();
248
-
249
- self .update_lock .lock ();
250
- defer self .update_lock .unlock ();
251
-
252
- var new_segments = try SharedPtr (List ).create (self .allocator , undefined );
253
- defer new_segments .release (self .allocator , .{self .allocator });
254
-
255
- new_segments .value .* = try List .init (self .allocator , self .segments .value .nodes .items .len );
256
- defer new_segments .value .deinit (self .allocator );
244
+ try new_segment .value .merge (& merger );
245
+ errdefer new_segment .value .cleanup ();
257
246
258
- var inserted_merged = false ;
259
- for (self .segments .value .nodes .items ) | node | {
260
- if (target .value .id .contains (node .value .id )) {
261
- if (! inserted_merged ) {
262
- new_segments .value .nodes .appendAssumeCapacity (target );
263
- inserted_merged = true ;
264
- }
265
- } else {
266
- new_segments .value .nodes .appendAssumeCapacity (node .acquire ());
267
- }
268
- }
247
+ var update = try self .beginUpdate ();
248
+ defer self .cleanupAfterUpdate (& update );
269
249
270
- try @call (.auto , preCommitFn , .{ ctx , new_segments .value });
250
+ try @call (.auto , preCommitFn , .{ ctx , update . segments .value });
271
251
272
252
lock .lock ();
273
253
defer lock .unlock ();
274
254
275
- self .segments . swap ( & new_segments );
255
+ self .commitUpdate ( & update );
276
256
277
257
return true ;
278
258
}
279
259
280
- pub fn update (self : * Self , changes : []const Change , lock : * std.Thread.RwLock , preCommitFn : anytype , ctx : anytype ) ! bool {
281
- var new_segment = try List .createSegment (self .allocator , self .options );
282
- errdefer List .destroySegment (self .allocator , & new_segment );
260
+ pub const Update = struct {
261
+ manager : * Self ,
262
+ segments : SharedPtr (List ),
263
+ committed : bool = false ,
283
264
284
- try new_segment .value .build (changes );
285
- errdefer new_segment .value .cleanup ();
265
+ pub fn removeSegment (self : * @This (), node : List .Node ) void {
266
+ self .manager .segments .value .removeSegmentInto (self .segments .value , node );
267
+ }
286
268
269
+ pub fn appendSegment (self : * @This (), node : List .Node ) void {
270
+ self .manager .segments .value .appendSegmentInto (self .segments .value , node );
271
+ }
272
+
273
+ pub fn replaceMergedSegment (self : * @This (), node : List .Node ) void {
274
+ self .manager .segments .value .replaceMergedSegmentInto (self .segments .value , node );
275
+ }
276
+ };
277
+
278
+ pub fn beginUpdate (self : * Self ) ! Update {
287
279
self .update_lock .lock ();
288
- defer self .update_lock .unlock ();
280
+ errdefer self .update_lock .unlock ();
289
281
290
- var new_segments_list = try self . segments . value . appendSegment (self .allocator , new_segment );
291
- errdefer new_segments_list . deinit ( self .allocator );
282
+ var segments = try SharedPtr ( List ). create (self .allocator , List . initEmpty () );
283
+ errdefer self .releaseSegments ( & segments );
292
284
293
- var new_segments = try SharedPtr (List ).create (self .allocator , new_segments_list );
294
- defer new_segments .release (self .allocator , .{self .allocator });
285
+ try segments .value .nodes .ensureTotalCapacity (self .allocator , self .segments .value .nodes .items .len + 1 );
295
286
296
- try @call (.auto , preCommitFn , .{ ctx , new_segments .value });
287
+ return .{
288
+ .manager = self ,
289
+ .segments = segments ,
290
+ };
291
+ }
297
292
298
- lock .lock ();
299
- defer lock .unlock ();
293
+ pub fn commitUpdate (self : * Self , update : * Update ) void {
294
+ self .segments .swap (& update .segments );
295
+ self .update_lock .unlock ();
296
+ update .committed = true ;
297
+ }
300
298
301
- self .segments .swap (& new_segments );
299
+ pub fn cleanupAfterUpdate (self : * Self , update : * Update ) void {
300
+ if (! update .committed ) {
301
+ self .update_lock .unlock ();
302
+ }
303
+ update .segments .releaseWithCleanup (self .allocator , destroySegmentList , .{self });
304
+ }
302
305
303
- return true ;
306
+ fn destroySegmentList (segments : * List , self : * Self ) void {
307
+ for (segments .nodes .items ) | node | {
308
+ node .value .cleanup ();
309
+ }
310
+ segments .deinit (self .allocator );
304
311
}
305
312
};
306
313
}
0 commit comments