| ... | @@ -321,51 +321,57 @@ pub const FixedBufferAllocator = struct { | ... | @@ -321,51 +321,57 @@ pub const FixedBufferAllocator = struct { |
| 321 | fn free(allocator: *Allocator, bytes: []u8) void {} | 321 | fn free(allocator: *Allocator, bytes: []u8) void {} |
| 322 | }; | 322 | }; |
| 323 | | 323 | |
| 324 | /// lock free | 324 | pub const ThreadSafeFixedBufferAllocator = blk: { |
| 325 | pub const ThreadSafeFixedBufferAllocator = struct { | 325 | if (builtin.single_threaded) { |
| 326 | allocator: Allocator, | 326 | break :blk FixedBufferAllocator; |
| 327 | end_index: usize, | 327 | } else { |
| 328 | buffer: []u8, | 328 | /// lock free |
| | 329 | break :blk struct { |
| | 330 | allocator: Allocator, |
| | 331 | end_index: usize, |
| | 332 | buffer: []u8, |
| | 333 | |
| | 334 | pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator { |
| | 335 | return ThreadSafeFixedBufferAllocator{ |
| | 336 | .allocator = Allocator{ |
| | 337 | .allocFn = alloc, |
| | 338 | .reallocFn = realloc, |
| | 339 | .freeFn = free, |
| | 340 | }, |
| | 341 | .buffer = buffer, |
| | 342 | .end_index = 0, |
| | 343 | }; |
| | 344 | } |
| 329 | | 345 | |
| 330 | pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator { | 346 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { |
| 331 | return ThreadSafeFixedBufferAllocator{ | 347 | const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator); |
| 332 | .allocator = Allocator{ | 348 | var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst); |
| 333 | .allocFn = alloc, | 349 | while (true) { |
| 334 | .reallocFn = realloc, | 350 | const addr = @ptrToInt(self.buffer.ptr) + end_index; |
| 335 | .freeFn = free, | 351 | const rem = @rem(addr, alignment); |
| 336 | }, | 352 | const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); |
| 337 | .buffer = buffer, | 353 | const adjusted_index = end_index + march_forward_bytes; |
| 338 | .end_index = 0, | 354 | const new_end_index = adjusted_index + n; |
| 339 | }; | 355 | if (new_end_index > self.buffer.len) { |
| 340 | } | 356 | return error.OutOfMemory; |
| | 357 | } |
| | 358 | end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index]; |
| | 359 | } |
| | 360 | } |
| 341 | | 361 | |
| 342 | fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 { | 362 | fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { |
| 343 | const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator); | 363 | if (new_size <= old_mem.len) { |
| 344 | var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst); | 364 | return old_mem[0..new_size]; |
| 345 | while (true) { | 365 | } else { |
| 346 | const addr = @ptrToInt(self.buffer.ptr) + end_index; | 366 | const result = try alloc(allocator, new_size, alignment); |
| 347 | const rem = @rem(addr, alignment); | 367 | mem.copy(u8, result, old_mem); |
| 348 | const march_forward_bytes = if (rem == 0) 0 else (alignment - rem); | 368 | return result; |
| 349 | const adjusted_index = end_index + march_forward_bytes; | 369 | } |
| 350 | const new_end_index = adjusted_index + n; | | |
| 351 | if (new_end_index > self.buffer.len) { | | |
| 352 | return error.OutOfMemory; | | |
| 353 | } | 370 | } |
| 354 | end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index]; | | |
| 355 | } | | |
| 356 | } | | |
| 357 | | 371 | |
| 358 | fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 { | 372 | fn free(allocator: *Allocator, bytes: []u8) void {} |
| 359 | if (new_size <= old_mem.len) { | 373 | }; |
| 360 | return old_mem[0..new_size]; | | |
| 361 | } else { | | |
| 362 | const result = try alloc(allocator, new_size, alignment); | | |
| 363 | mem.copy(u8, result, old_mem); | | |
| 364 | return result; | | |
| 365 | } | | |
| 366 | } | 374 | } |
| 367 | | | |
| 368 | fn free(allocator: *Allocator, bytes: []u8) void {} | | |
| 369 | }; | 375 | }; |
| 370 | | 376 | |
| 371 | pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) { | 377 | pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) { |