@@ -302,8 +302,17 @@ pub const FixedBufferAllocator = struct {
302
302
}
303
303
304
304
fn realloc (allocator : * Allocator , old_mem : []u8 , new_size : usize , alignment : u29 ) ! []u8 {
305
+ const self = @fieldParentPtr (FixedBufferAllocator , "allocator" , allocator );
306
+ assert (old_mem .len <= self .end_index );
305
307
if (new_size <= old_mem .len ) {
306
308
return old_mem [0.. new_size ];
309
+ } else if (old_mem .ptr == self .buffer .ptr + self .end_index - old_mem .len ) {
310
+ const start_index = self .end_index - old_mem .len ;
311
+ const new_end_index = start_index + new_size ;
312
+ if (new_end_index > self .buffer .len ) return error .OutOfMemory ;
313
+ const result = self .buffer [start_index .. new_end_index ];
314
+ self .end_index = new_end_index ;
315
+ return result ;
307
316
} else {
308
317
const result = try alloc (allocator , new_size , alignment );
309
318
mem .copy (u8 , result , old_mem );
@@ -467,6 +476,35 @@ test "FixedBufferAllocator" {
467
476
try testAllocatorLargeAlignment (& fixed_buffer_allocator .allocator );
468
477
}
469
478
479
+ test "FixedBufferAllocator Reuse memory on realloc" {
480
+ var small_fixed_buffer : [10 ]u8 = undefined ;
481
+ // check if we re-use the memory
482
+ {
483
+ var fixed_buffer_allocator = FixedBufferAllocator .init (small_fixed_buffer [0.. ]);
484
+
485
+ var slice0 = try fixed_buffer_allocator .allocator .alloc (u8 , 5 );
486
+ assert (slice0 .len == 5 );
487
+ var slice1 = try fixed_buffer_allocator .allocator .realloc (u8 , slice0 , 10 );
488
+ assert (slice1 .ptr == slice0 .ptr );
489
+ assert (slice1 .len == 10 );
490
+ debug .assertError (fixed_buffer_allocator .allocator .realloc (u8 , slice1 , 11 ), error .OutOfMemory );
491
+ }
492
+ // check that we don't re-use the memory if it's not the most recent block
493
+ {
494
+ var fixed_buffer_allocator = FixedBufferAllocator .init (small_fixed_buffer [0.. ]);
495
+
496
+ var slice0 = try fixed_buffer_allocator .allocator .alloc (u8 , 2 );
497
+ slice0 [0 ] = 1 ;
498
+ slice0 [1 ] = 2 ;
499
+ var slice1 = try fixed_buffer_allocator .allocator .alloc (u8 , 2 );
500
+ var slice2 = try fixed_buffer_allocator .allocator .realloc (u8 , slice0 , 4 );
501
+ assert (slice0 .ptr != slice2 .ptr );
502
+ assert (slice1 .ptr != slice2 .ptr );
503
+ assert (slice2 [0 ] == 1 );
504
+ assert (slice2 [1 ] == 2 );
505
+ }
506
+ }
507
+
470
508
test "ThreadSafeFixedBufferAllocator" {
471
509
var fixed_buffer_allocator = ThreadSafeFixedBufferAllocator .init (test_fixed_buffer_allocator_memory [0.. ]);
472
510
@@ -482,12 +520,14 @@ fn testAllocator(allocator: *mem.Allocator) !void {
482
520
item .* = try allocator .create (@intCast (i32 , i ));
483
521
}
484
522
485
- for (slice ) | item , i | {
523
+ slice = try allocator .realloc (* i32 , slice , 20000 );
524
+ assert (slice .len == 20000 );
525
+
526
+ for (slice [0.. 100]) | item , i | {
527
+ assert (item .* == @intCast (i32 , i ));
486
528
allocator .destroy (item );
487
529
}
488
530
489
- slice = try allocator .realloc (* i32 , slice , 20000 );
490
- assert (slice .len == 20000 );
491
531
slice = try allocator .realloc (* i32 , slice , 50 );
492
532
assert (slice .len == 50 );
493
533
slice = try allocator .realloc (* i32 , slice , 25 );
0 commit comments