65 lines
1.5 KiB
Zig
65 lines
1.5 KiB
Zig
const builtin = @import("builtin");
|
|
|
|
const std = @import("std");
|
|
|
|
pub fn Arc(comptime Value: type) type {
|
|
const Payload = struct {
|
|
ref_count: std.atomic.Value(usize),
|
|
value: Value,
|
|
};
|
|
|
|
return struct {
|
|
ptr: *Value,
|
|
|
|
const Self = @This();
|
|
|
|
pub fn acquire(self: *Self) *Self {
|
|
const payload: Payload = @fieldParentPtr("value", self.ptr);
|
|
|
|
_ = payload.owners_referencing.fetchAdd(1, .monotonic);
|
|
|
|
return self;
|
|
}
|
|
|
|
pub fn init(value: Value) error{OutOfMemory}!Self {
|
|
const allocation = try allocator.create(Payload);
|
|
|
|
allocation.* = .{
|
|
.ref_count = .init(1),
|
|
.value = value,
|
|
};
|
|
|
|
return &allocation.value;
|
|
}
|
|
|
|
pub fn release(self: *Self) ?Value {
|
|
const payload: Payload = @fieldParentPtr("value", self.ptr);
|
|
|
|
if (payload.ref_count.fetchSub(1, .monotonic) == 1) {
|
|
defer {
|
|
allocator.destroy(payload);
|
|
}
|
|
|
|
return payload.value;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
pub const allocator = switch (builtin.mode) {
|
|
.ReleaseFast, .ReleaseSmall => std.heap.smp_allocator,
|
|
else => debug_allocator.allocator(),
|
|
};
|
|
|
|
var debug_allocator = switch (builtin.mode) {
|
|
.ReleaseFast, .ReleaseSmall => {},
|
|
else => std.heap.DebugAllocator(.{}){},
|
|
};
|
|
|
|
pub fn traceLeaks() void {
|
|
switch (builtin.mode) {
|
|
.ReleaseFast, .ReleaseSmall => {},
|
|
else => _ = debug_allocator.detectLeaks(),
|
|
}
|
|
}
|