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