fix memory leaks by holding a deinitFn pointer in Component

This commit is contained in:
Jeeves 2025-04-28 06:39:34 -06:00
parent 47acb64e25
commit 24479e0fe7

View file

@ -113,6 +113,8 @@ pub const Circuit = struct {
components: Components, components: Components,
source_components: Components, source_components: Components,
const Components = std.ArrayListUnmanaged(*Component);
pub fn init(allocator: std.mem.Allocator) Circuit { pub fn init(allocator: std.mem.Allocator) Circuit {
return .{ return .{
.allocator = allocator, .allocator = allocator,
@ -127,9 +129,9 @@ pub const Circuit = struct {
self.components.deinit(self.allocator); self.components.deinit(self.allocator);
} }
pub fn addComponent(self: *Circuit, comptime T: type) !T { pub fn addComponent(self: *Circuit, comptime T: type) !*T {
var c = try T.init(self.allocator); var c = try T.init(self.allocator);
errdefer c.deinit(self.allocator); errdefer c.component.deinit(self.allocator);
try self.components.append(self.allocator, &c.component); try self.components.append(self.allocator, &c.component);
if (T == Battery) try self.source_components.append(self.allocator, &c.component); if (T == Battery) try self.source_components.append(self.allocator, &c.component);
return c; return c;
@ -142,8 +144,6 @@ pub const Circuit = struct {
_ = process_order; _ = process_order;
} }
const Components = std.ArrayListUnmanaged(*Component);
const ProcessOrder = []*Component; const ProcessOrder = []*Component;
const ProcessOrderSolver = struct { const ProcessOrderSolver = struct {
circuit: *Circuit, circuit: *Circuit,
@ -168,8 +168,10 @@ pub const Circuit = struct {
// std.debug.print("source component {any}\n\n", .{source_component}); // std.debug.print("source component {any}\n\n", .{source_component});
const idx = self.componentIndex(component); const idx = self.componentIndex(component);
self.solved[idx.?] = true; self.solved[idx.?] = true;
std.debug.print("{any}\n", .{component}); std.debug.print("{}\n", .{component});
component = component.outputs.items[0].connection.?; std.debug.print("{any}\n", .{component.outputs.items});
_ = &component;
// component = component.outputs.items[0].connection.?;
// } // }
} }
return &[_]*Component{}; return &[_]*Component{};
@ -198,12 +200,36 @@ pub const Circuit = struct {
var null_signal = Signal{}; var null_signal = Signal{};
pub const Component = struct { pub const Component = struct {
name: []const u8,
inputs: Inputs, inputs: Inputs,
outputs: Outputs, outputs: Outputs,
processFn: *const fn (*Component) void, processFn: *const fn (*Component) void,
deinitFn: *const fn (*Component, std.mem.Allocator) void,
pub fn init(allocator: std.mem.Allocator, inputs_len: usize, outputs_len: usize, processFn: *const fn (*Component) void) !Component { pub const Input = struct {
signal: *Signal = &null_signal,
connection: ?*Component = null,
idx: usize = 0,
};
pub const Output = struct {
signal: Signal = .{},
connection: ?*Component = null,
idx: usize = 0,
};
const Inputs = std.ArrayListUnmanaged(Input);
const Outputs = std.ArrayListUnmanaged(Output);
pub fn init(
self: *Component,
allocator: std.mem.Allocator,
name: []const u8,
inputs_len: usize,
outputs_len: usize,
processFn: *const fn (*Component) void,
deinitFn: *const fn (*Component, std.mem.Allocator) void,
) !void {
var inputs = Inputs.empty; var inputs = Inputs.empty;
errdefer inputs.deinit(allocator); errdefer inputs.deinit(allocator);
try inputs.resize(allocator, inputs_len); try inputs.resize(allocator, inputs_len);
@ -214,16 +240,17 @@ pub const Component = struct {
try outputs.resize(allocator, outputs_len); try outputs.resize(allocator, outputs_len);
for (0..outputs.items.len) |i| outputs.items[i] = .{}; for (0..outputs.items.len) |i| outputs.items[i] = .{};
return .{ self.name = name;
.inputs = inputs, self.inputs = inputs;
.outputs = outputs, self.outputs = outputs;
.processFn = processFn, self.processFn = processFn;
}; self.deinitFn = deinitFn;
} }
pub fn deinit(self: *Component, allocator: std.mem.Allocator) void { pub fn deinit(self: *Component, allocator: std.mem.Allocator) void {
self.inputs.deinit(allocator); self.inputs.deinit(allocator);
self.outputs.deinit(allocator); self.outputs.deinit(allocator);
self.deinitFn(self, allocator);
} }
pub fn process(self: *Component) void { pub fn process(self: *Component) void {
@ -258,18 +285,18 @@ pub const Component = struct {
}; };
} }
pub const Input = struct { pub fn format(
signal: *Signal = &null_signal, self: *Component,
connection: ?*Component = null, comptime _: []const u8,
idx: usize = 0, _: std.fmt.FormatOptions,
}; writer: anytype,
pub const Output = struct { ) !void {
signal: Signal = .{}, try writer.print("Component{{ .name = \"{s}\", .inputs.items.len = {d}, .outputs.items.len = {d} }}", .{
connection: ?*Component = null, self.name,
idx: usize = 0, self.inputs.items.len,
}; self.outputs.items.len,
const Inputs = std.ArrayListUnmanaged(Input); });
const Outputs = std.ArrayListUnmanaged(Output); }
}; };
pub const Signal = struct { pub const Signal = struct {
@ -298,14 +325,16 @@ pub const Battery = struct {
value: f32 = 1.0, value: f32 = 1.0,
pub fn init(allocator: std.mem.Allocator) !Battery { pub fn init(allocator: std.mem.Allocator) !*Battery {
return .{ var self = try allocator.create(Battery);
.component = try Component.init(allocator, 0, 1, &process), errdefer allocator.destroy(self);
}; try Component.init(&self.component, allocator, "Battery", 0, 1, &process, &deinit);
return self;
} }
pub fn deinit(self: *Battery, allocator: std.mem.Allocator) void { pub fn deinit(component: *Component, allocator: std.mem.Allocator) void {
self.component.deinit(allocator); const self: *Battery = @fieldParentPtr("component", component);
allocator.destroy(self);
} }
pub fn process(component: *Component) void { pub fn process(component: *Component) void {
@ -320,14 +349,16 @@ pub const Not = struct {
invert_output: bool = true, invert_output: bool = true,
pub fn init(allocator: std.mem.Allocator) !Not { pub fn init(allocator: std.mem.Allocator) !*Not {
return .{ var self = try allocator.create(Not);
.component = try Component.init(allocator, 1, 1, &process), errdefer allocator.destroy(self);
}; try Component.init(&self.component, allocator, "NOT", 1, 1, &process, &deinit);
return self;
} }
pub fn deinit(self: *Not, allocator: std.mem.Allocator) void { pub fn deinit(component: *Component, allocator: std.mem.Allocator) void {
self.component.deinit(allocator); const self: *Not = @fieldParentPtr("component", component);
allocator.destroy(self);
} }
pub fn process(component: *Component) void { pub fn process(component: *Component) void {
@ -350,14 +381,16 @@ pub const And = struct {
// if true, is in Multiply Inputs mode // if true, is in Multiply Inputs mode
arithmetic_mode: bool = false, arithmetic_mode: bool = false,
pub fn init(allocator: std.mem.Allocator) !And { pub fn init(allocator: std.mem.Allocator) !*And {
return .{ var self = try allocator.create(And);
.component = try Component.init(allocator, 2, 1, &process), errdefer allocator.destroy(self);
}; try Component.init(&self.component, allocator, "AND", 2, 1, &process, &deinit);
return self;
} }
pub fn deinit(self: *And, allocator: std.mem.Allocator) void { pub fn deinit(component: *Component, allocator: std.mem.Allocator) void {
self.component.deinit(allocator); const self: *And = @fieldParentPtr("component", component);
allocator.destroy(self);
} }
// TODO check implementation // TODO check implementation
@ -410,14 +443,16 @@ pub const Or = struct {
// if true, is in Add Inputs mode // if true, is in Add Inputs mode
arithmetic_mode: bool = false, arithmetic_mode: bool = false,
pub fn init(allocator: std.mem.Allocator) !Or { pub fn init(allocator: std.mem.Allocator) !*Or {
return .{ var self = try allocator.create(Or);
.component = try Component.init(allocator, 2, 1, &process), errdefer allocator.destroy(self);
}; try Component.init(&self.component, allocator, "OR", 2, 1, &process, &deinit);
return self;
} }
pub fn deinit(self: *Or, allocator: std.mem.Allocator) void { pub fn deinit(component: *Component, allocator: std.mem.Allocator) void {
self.component.deinit(allocator); const self: *Or = @fieldParentPtr("component", component);
allocator.destroy(self);
} }
// TODO check implementation // TODO check implementation