lib/alloc/src/process.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const build_options = @import("build_options");
 3 
 4 const phase = @import("alloc_phase");
 5 
 6 const Allocator = std.mem.Allocator;
 7 
 8 pub const ProcessPhaseMode = enum {
 9     off,
10     observe,
11     seal,
12 };
13 
14 pub const mode: ProcessPhaseMode = parseMode();
15 
16 const ProcessPhaseAllocator = switch (mode) {
17     .off => void,
18     .observe => phase.ObservingPhaseAllocator,
19     .seal => phase.SealedPhaseAllocator,
20 };
21 
22 var lock: std.atomic.Mutex = .unlocked;
23 var initialized = false;
24 var storage: ProcessPhaseAllocator = undefined;
25 var handle: Allocator = undefined;
26 
27 pub fn wrap(backing: Allocator) Allocator {
28     if (comptime mode == .off) return backing;
29     lockInit();
30     defer unlockInit();
31     if (!initialized) {
32         storage = ProcessPhaseAllocator.init(backing) catch
33             @panic("out of memory initializing process allocator phase");
34         handle = storage.initializationAllocator();
35         initialized = true;
36     }
37     return handle;
38 }
39 
40 pub fn seal() void {
41     if (comptime mode == .off) return;
42     lockInit();
43     defer unlockInit();
44     if (!initialized) @panic("process allocator phase sealed before first use");
45     storage.seal();
46 }
47 
48 pub fn beginTeardown() void {
49     if (comptime mode == .off) return;
50     lockInit();
51     defer unlockInit();
52     if (!initialized) @panic("process allocator phase teardown before first use");
53     storage.beginTeardown();
54 }
55 
56 pub fn violations() ?phase.PhaseViolations {
57     if (comptime mode == .off) return null;
58     lockInit();
59     defer unlockInit();
60     if (!initialized) return .{};
61     return storage.violations();
62 }
63 
64 pub fn violationSites() ?phase.ViolationSites {
65     if (comptime mode != .observe) return null;
66     lockInit();
67     defer unlockInit();
68     if (!initialized) return .{};
69     return storage.violationSites();
70 }
71 
72 pub fn currentPhase() ?phase.capacity.Phase {
73     if (comptime mode == .off) return null;
74     lockInit();
75     defer unlockInit();
76     if (!initialized) return .initialization;
77     return storage.phase();
78 }
79 
80 fn parseMode() ProcessPhaseMode {
81     if (std.mem.eql(u8, build_options.allocator_phase, "off")) return .off;
82     if (std.mem.eql(u8, build_options.allocator_phase, "observe")) return .observe;
83     if (std.mem.eql(u8, build_options.allocator_phase, "seal")) return .seal;
84     @compileError("unknown allocator phase mode");
85 }
86 
87 fn lockInit() void {
88     while (!lock.tryLock()) std.atomic.spinLoopHint();
89 }
90 
91 fn unlockInit() void {
92     lock.unlock();
93 }