diff --git a/src/app_common/Model.zig b/src/app_common/Model.zig index 3557170..63c3ad3 100644 --- a/src/app_common/Model.zig +++ b/src/app_common/Model.zig @@ -36,6 +36,8 @@ pub fn preCurrentItemsUnload(ctx: *anyopaque, tab: *Tab) void { } pub fn deinit(self: *@This()) void { + self.appState.tabPreCurrentItemsUnload.detach(&self._private.preCurrentItemsUnload); + self.appState.deinit(); self.current_items_allocator.deinit(); } diff --git a/src/app_common/root.zig b/src/app_common/root.zig index d6ee808..4df117b 100644 --- a/src/app_common/root.zig +++ b/src/app_common/root.zig @@ -10,22 +10,22 @@ pub fn data_loop(vm: *Model) void { } vm.usage_number.data -= 1; } -fn inner_loop(vm: *Model) !void { - const tab = vm.appState.currentTab; +fn inner_loop(appCommonModel: *Model) !void { + const tab = appCommonModel.appState.currentTab; + tab.currentItems.mutex.lock(); + defer tab.currentItems.mutex.unlock(); + if (tab.currentItemsChanged) { std.Thread.sleep(10 * std.time.ns_per_ms); - tab.currentItems.mutex.lock(); - defer tab.currentItems.mutex.unlock(); - - if (tab.currentItems.data) |tab_current_items| { + if (tab.currentItems.data) |*tab_current_items| { { - vm.current_items.mutex.lock(); - defer vm.current_items.mutex.unlock(); - vm.current_items.data = null; + appCommonModel.current_items.mutex.lock(); + defer appCommonModel.current_items.mutex.unlock(); + appCommonModel.current_items.data = null; } - _ = vm.current_items_allocator.reset(.retain_capacity); - const allocator = vm.current_items_allocator.allocator(); + _ = appCommonModel.current_items_allocator.reset(.retain_capacity); + const allocator = appCommonModel.current_items_allocator.allocator(); const items = try allocator.alloc(*models.Item, tab_current_items.items.len); for (tab_current_items.items, 0..) |item, i| { @@ -40,9 +40,9 @@ fn inner_loop(vm: *Model) !void { } }.sort); - vm.current_items.mutex.lock(); - defer vm.current_items.mutex.unlock(); - vm.current_items.data = items; + appCommonModel.current_items.mutex.lock(); + defer appCommonModel.current_items.mutex.unlock(); + appCommonModel.current_items.data = items; tab.currentItemsChanged = false; } } diff --git a/src/console/action_map.zig b/src/console/action_map.zig index f7970f1..b228739 100644 --- a/src/console/action_map.zig +++ b/src/console/action_map.zig @@ -1,9 +1,10 @@ -pub fn handle_key(key: vaxis.Key, appState: *AppState) !void { +pub fn handle_key(key: vaxis.Key, appState: *AppState, arena: std.mem.Allocator) !void { if (key.matches(vaxis.Key.left, .{})) { - try handle_action(Action.GoUp, appState); + try handle_action(Action.GoUp, appState, arena); } } +const std = @import("std"); const vaxis = @import("vaxis"); const handle_action = @import("../core/action/action_handler.zig").handle; const Action = @import("../core/action/action.zig").Action; diff --git a/src/console/main.zig b/src/console/main.zig index ca14786..5bb5b8e 100644 --- a/src/console/main.zig +++ b/src/console/main.zig @@ -3,7 +3,7 @@ const Model = struct { crash: bool = false, allocator: std.mem.Allocator, current_items_view: *vxfw.ListView, - core_model: CoreModel, + app_common_model: AppCommonModel, root_provider: *RootProvider, /// Helper function to return a vxfw.Widget struct @@ -35,7 +35,9 @@ const Model = struct { // return ctx.requestFocus(vm.current_items_view.widget()); // } - handle_key(key, &vm.core_model.appState) catch {}; + var arena = std.heap.ArenaAllocator.init(vm.allocator); + defer arena.deinit(); + handle_key(key, &vm.app_common_model.appState, arena.allocator()) catch {}; }, .focus_in => return ctx.requestFocus(vm.current_items_view.widget()), else => {}, @@ -88,7 +90,7 @@ const Model = struct { }; try rootWidgets.append(list_surface); - const current_location_text = if (vm.core_model.appState.currentTab.currentLocation) |loc| loc.item.fullName.path else ""; + const current_location_text = if (vm.app_common_model.appState.currentTab.currentLocation) |loc| loc.item.fullName.path else ""; const current_location_text_element = try ctx.arena.create(vxfw.Text); current_location_text_element.* = vxfw.Text{ .text = current_location_text, @@ -117,9 +119,9 @@ const Model = struct { fn createCurrentItems(ctx: vxfw.DrawContext, vm: *Model) !void { if (vm.crash) @panic("asd123"); - vm.core_model.current_items.mutex.lock(); - defer vm.core_model.current_items.mutex.unlock(); - const text_items = if (vm.core_model.current_items.data) |items| blk: { + vm.app_common_model.current_items.mutex.lock(); + defer vm.app_common_model.current_items.mutex.unlock(); + const text_items = if (vm.app_common_model.current_items.data) |items| blk: { const children = try ctx.arena.alloc(*vxfw.Text, items.len); for (0.., items[0..children.len]) |i, child| { const is_active = i == vm.current_items_view.cursor; @@ -264,20 +266,20 @@ pub fn main() !void { const model = try allocator.create(Model); defer allocator.destroy(model); - var core_model: CoreModel = undefined; - try CoreModel.init(&core_model, std.heap.ArenaAllocator.init(allocator), appState); + var app_common_model: AppCommonModel = undefined; + try AppCommonModel.init(&app_common_model, std.heap.ArenaAllocator.init(allocator), appState); + defer app_common_model.deinit(); model.* = .{ .allocator = allocator, - .core_model = core_model, + .app_common_model = app_common_model, .current_items_view = &list, .root_provider = &rootProvider, }; - defer model.core_model.deinit(); - model.core_model.usage_number.data += 1; + model.app_common_model.usage_number.data += 1; - try pool.spawn(core.data_loop, .{&model.core_model}); + try pool.spawn(core.data_loop, .{&model.app_common_model}); var app = try vxfw.App.init(allocator); defer app.deinit(); @@ -285,10 +287,10 @@ pub fn main() !void { try app.run(model.widget(), .{}); // std.Thread.sleep(10 * std.time.ns_per_s); - model.core_model.usage_number.data -= 1; - model.core_model.running = false; + model.app_common_model.usage_number.data -= 1; + model.app_common_model.running = false; - while (model.core_model.usage_number.data > 0) { + while (model.app_common_model.usage_number.data > 0) { std.Thread.sleep(10 * std.time.ns_per_ms); } } @@ -303,7 +305,7 @@ const RootProvider = @import("../core/provider/root.zig").RootProvider; const local_provider = @import("../core/provider/local.zig"); const Tab = @import("../core/tab/tab.zig").Tab; const locked = @import("../core/sync.zig").locked; -const CoreModel = @import("../app_common/Model.zig"); +const AppCommonModel = @import("../app_common/Model.zig"); const core = @import("../app_common/root.zig"); const AppState = @import("../core/app_state.zig").AppState; const handle_key = @import("./action_map.zig").handle_key; diff --git a/src/core/action/action_handler.zig b/src/core/action/action_handler.zig index e83e7cd..d8ba7b5 100644 --- a/src/core/action/action_handler.zig +++ b/src/core/action/action_handler.zig @@ -1,10 +1,11 @@ -pub fn handle(action: Action, appState: *AppState) !void { +pub fn handle(action: Action, appState: *AppState, arena: std.mem.Allocator) !void { switch (action) { .GoUp => { if (appState.currentTab.currentLocation) |currentLocation| { const parent = currentLocation.item.parent; if (parent) |p| { - try appState.currentTab.setCurrentLocation(.{ .path = p.path.path }); + const path = try arena.dupe(u8, p.path.path); + try appState.currentTab.setCurrentLocation(.{ .path = path }); } else return error.NoParent; } else return error.NoCurrentLocation; }, @@ -12,6 +13,7 @@ pub fn handle(action: Action, appState: *AppState) !void { } } +const std = @import("std"); const Action = @import("action.zig").Action; const AppState = @import("../app_state.zig").AppState; const RootProvider = @import("../provider/root.zig").RootProvider; diff --git a/src/core/app_state.zig b/src/core/app_state.zig index 44e584e..986c545 100644 --- a/src/core/app_state.zig +++ b/src/core/app_state.zig @@ -35,7 +35,11 @@ pub const AppState = struct { } pub fn deinit(self: *AppState) void { + self.tabPreCurrentItemsUnload.deinit(); self.currentTabChanged.deinit(); + for (self.tabs.items) |*tab| { + tab.deinit(); + } self.tabs.deinit(); } diff --git a/src/core/models.zig b/src/core/models.zig index ed8c0bd..32d310f 100644 --- a/src/core/models.zig +++ b/src/core/models.zig @@ -18,6 +18,11 @@ pub const Item = struct { self.allocator.free(self.displayName); self.allocator.free(self.fullName.path); self.allocator.free(self.nativePath.path); + + if (self.parent) |p| { + self.allocator.free(p.path.path); + } + for (self.errors.items) |e| { self.allocator.free(e.content); } @@ -54,6 +59,7 @@ pub const Container = struct { self.item.allocator.free(itemFullName.path); } self.children.deinit(); + self.item.allocator.destroy(self); } }; diff --git a/src/core/observable.zig b/src/core/observable.zig index 1c5df59..04c19ff 100644 --- a/src/core/observable.zig +++ b/src/core/observable.zig @@ -18,7 +18,7 @@ pub fn Observable(T: type) type { } pub fn detach(self: *Self, obs: *const Observer(T)) void { - if (std.mem.indexOfScalar(*const Observer, self.observers.items, obs)) |index| { + if (std.mem.indexOfScalar(*const Observer(T), self.observers.items, obs)) |index| { _ = self.observers.swapRemove(index); } } diff --git a/src/core/tab/tab.zig b/src/core/tab/tab.zig index bd6a3a5..eebdbb8 100644 --- a/src/core/tab/tab.zig +++ b/src/core/tab/tab.zig @@ -36,7 +36,6 @@ pub const Tab = struct { pub fn setCurrentLocation(self: *Tab, newLocationFullName: models.FullName) !void { if (self.currentLocation) |c| { c.item.deinit(); - self.allocator.destroy(c); } errdefer { @@ -45,6 +44,9 @@ pub const Tab = struct { } const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator); + errdefer { + newLocation.deinit(); + } const newLocationContainer = switch (newLocation.item) { .container => |c| c, @@ -53,6 +55,7 @@ pub const Tab = struct { self.currentLocation = newLocationContainer; self.currentLocationChanged.notify(newLocationContainer); + std.debug.print("\nASD1\n", .{}); //TODO: Proper error handling std.Thread.Pool.spawn(self.threadPool, loadItemsWrapper, .{ self, newLocationContainer }) catch unreachable; @@ -68,17 +71,12 @@ pub const Tab = struct { self.preCurrentItemsUnload.notify(self); - if (self.currentItems.data) |items| { - items.deinit(); - } - self.currentItems.data = null; } + //TODO: half the capacity to prevent "leaking" after a huuuge container has been opened once _ = self._private.currentItemsAllocator.reset(.retain_capacity); - - const arenaAllocator = &self._private.currentItemsAllocator; - const arena = arenaAllocator.allocator(); + const arena = self._private.currentItemsAllocator.allocator(); var threadSafeAllocator = std.heap.ThreadSafeAllocator{ .child_allocator = arena }; const allocator = threadSafeAllocator.allocator(); @@ -121,6 +119,7 @@ pub const Tab = struct { defer self.currentItems.mutex.unlock(); self.currentItemsChanged = true; } + std.debug.print("\nASDX\n", .{}); } pub fn deinit(self: *Tab) void {