@@ -228,3 +228,153 @@ pub const SegmentMergeOptions = struct {
228
228
}
229
229
}
230
230
};
231
+
232
+ const MemorySegment = @import ("MemorySegment.zig" );
233
+ const FileSegment = @import ("FileSegment.zig" );
234
+
235
+ pub const AnySegment = union (enum ) {
236
+ file : FileSegment ,
237
+ memory : MemorySegment ,
238
+
239
+ pub fn search (self : AnySegment , sorted_hashes : []const u32 , results : * SearchResults ) ! void {
240
+ switch (self ) {
241
+ .file = > | segment | try segment .search (sorted_hashes , results ),
242
+ .memory = > | segment | try segment .search (sorted_hashes , results ),
243
+ }
244
+ }
245
+
246
+ pub fn getMaxCommitId (self : AnySegment ) u64 {
247
+ switch (self ) {
248
+ .file = > | segment | return segment .max_commit_id ,
249
+ .memory = > | segment | return segment .max_commit_id ,
250
+ }
251
+ }
252
+ };
253
+
254
+ pub const AnySegmentNode = struct {
255
+ segment : AnySegment ,
256
+ refs : std .atomic .Value (u32 ),
257
+ next : std .atomic .Value (? * AnySegmentNode ),
258
+
259
+ pub fn create (comptime Segment : type , allocator : std.mem.Allocator ) ! * AnySegmentNode {
260
+ const result = try allocator .create (AnySegmentNode );
261
+ errdefer allocator .destroy (result );
262
+
263
+ result .* = .{
264
+ .segment = undefined ,
265
+ .refs = std .atomic .Value (u32 ).init (0 ),
266
+ .next = std .atomic .Value (? * AnySegmentNode ).init (null ),
267
+ };
268
+
269
+ inline for (@typeInfo (AnySegment ).Union .fields ) | f | {
270
+ if (f .type == Segment ) {
271
+ result .segment = @unionInit (AnySegment , f .name , Segment .init (allocator ));
272
+ break ;
273
+ }
274
+ } else {
275
+ @compileError ("Unknown segment type '" ++ @typeName (Segment ) ++ "'" );
276
+ }
277
+
278
+ return result ;
279
+ }
280
+
281
+ pub fn destroy (self : * AnySegmentNode , allocator : std.mem.Allocator ) void {
282
+ const refs = self .refs .load (.acquire );
283
+ if (refs != 0 ) {
284
+ std .debug .panic ("trying to destroy segment with {} reference(s)" , .{refs });
285
+ }
286
+ allocator .destroy (self );
287
+ }
288
+
289
+ pub fn ref (self : * AnySegmentNode ) void {
290
+ _ = self .refs .fetchAdd (1 , .release );
291
+ }
292
+
293
+ pub fn unref (self : * AnySegmentNode ) void {
294
+ _ = self .refs .fetchSub (1 , .release );
295
+ }
296
+
297
+ pub fn search (self : * AnySegmentNode , sorted_hashes : []const u32 , results : * SearchResults ) ! void {
298
+ self .ref ();
299
+ defer self .unref ();
300
+ return self .segment .search (sorted_hashes , results );
301
+ }
302
+
303
+ pub fn getMaxCommitId (self : * AnySegmentNode ) u64 {
304
+ self .ref ();
305
+ defer self .unref ();
306
+ return self .segment .getMaxCommitId ();
307
+ }
308
+ };
309
+
310
+ pub const AnySegmentList = struct {
311
+ allocator : std.mem.Allocator ,
312
+ head : std .atomic .Value (? * AnySegmentNode ),
313
+
314
+ pub fn init (allocator : std.mem.Allocator ) AnySegmentList {
315
+ return .{
316
+ .allocator = allocator ,
317
+ .head = std .atomic .Value (? * AnySegmentNode ).init (null ),
318
+ };
319
+ }
320
+
321
+ pub fn count (self : * AnySegmentList ) usize {
322
+ var result : usize = 0 ;
323
+ var iter = self .head .load (.acquire );
324
+ while (iter ) | node | : (iter = node .next .load (.acquire )) {
325
+ result += 1 ;
326
+ }
327
+ return result ;
328
+ }
329
+
330
+ pub fn search (self : * AnySegmentList , sorted_hashes : []const u32 , results : * SearchResults , deadline : Deadline ) ! void {
331
+ var iter = self .head .load (.acquire );
332
+ while (iter ) | node | : (iter = node .next .load (.acquire )) {
333
+ if (deadline .isExpired ()) {
334
+ return error .Timeout ;
335
+ }
336
+ try node .search (sorted_hashes , results );
337
+ }
338
+ }
339
+
340
+ pub fn getMaxCommitId (self : * AnySegmentList ) u64 {
341
+ var result : u64 = 0 ;
342
+ var iter = self .head .load (.acquire );
343
+ while (iter ) | node | : (iter = node .next .load (.acquire )) {
344
+ result = @max (result , node .getMaxCommitId ());
345
+ }
346
+ return result ;
347
+ }
348
+
349
+ pub fn prepend (self : * AnySegmentList , node : * AnySegmentNode ) void {
350
+ var head = self .head .load (.acquire );
351
+ while (true ) {
352
+ node .next .store (head , .release );
353
+ head = self .head .cmpxchgWeak (head , node , .seq_cst , .seq_cst ) orelse break ;
354
+ }
355
+ }
356
+
357
+ pub fn swap (self : * AnySegmentList , new_node : * AnySegmentNode , old_node : * AnySegmentNode , old_count : usize ) void {
358
+ _ = self ;
359
+ _ = new_node ;
360
+ _ = old_node ;
361
+ _ = old_count ;
362
+ }
363
+ };
364
+
365
+ test "AnySegment" {
366
+ var node1 = try AnySegmentNode .create (MemorySegment , std .testing .allocator );
367
+ defer node1 .destroy (std .testing .allocator );
368
+
369
+ var node2 = try AnySegmentNode .create (MemorySegment , std .testing .allocator );
370
+ defer node2 .destroy (std .testing .allocator );
371
+
372
+ var list = AnySegmentList .init (std .testing .allocator );
373
+ list .prepend (node1 );
374
+ list .swap (node2 , node1 , 1 );
375
+
376
+ var results = SearchResults .init (std .testing .allocator );
377
+ defer results .deinit ();
378
+
379
+ try list .search (&[_ ]u32 {}, & results , .{});
380
+ }
0 commit comments