diff --git a/src/app_common/Model.zig b/src/app_common/Model.zig index dcc799e..7892db0 100644 --- a/src/app_common/Model.zig +++ b/src/app_common/Model.zig @@ -1,6 +1,6 @@ running: bool = true, usage_number: locked(u16) = .{ .data = 0 }, -current_items: locked(?[]*models.Item) = .{ .data = null }, +current_items: locked(?[]Arc(*models.Item).Weak) = .{ .data = null }, allocator: std.mem.Allocator, appState: AppState, _private: Private, @@ -24,20 +24,36 @@ pub fn init(model: *Self, allocator: std.mem.Allocator, appState: AppState) !voi try model.appState.tabPreCurrentItemsUnload.attach(&model._private.preCurrentItemsUnload); } -pub fn updateCurrentItems(self: *Self, tab_current_items: *std.ArrayList(*models.Item)) !void { +pub fn updateCurrentItems(self: *Self, tab_current_items: *std.ArrayList(Arc(*models.Item))) !void { self.resetCurrentItems(); - const items = try self.allocator.alloc(*models.Item, tab_current_items.items.len); + var items = try self.allocator.alloc(Arc(*models.Item).Weak, tab_current_items.items.len); errdefer { self.allocator.free(items); self.current_items.data = null; } - for (tab_current_items.items, 0..) |item, i| { - items[i] = item; + for (tab_current_items.items, 0..) |*item, i| { + items[i] = item.downgrade(); } - std.mem.sort(*models.Item, items, {}, struct { - fn sort(_: void, lhs: *models.Item, rhs: *models.Item) bool { + std.mem.sort(Arc(*models.Item).Weak, items, {}, struct { + fn sort(_: void, lhs_weak: Arc(*models.Item).Weak, rhs_weak: Arc(*models.Item).Weak) bool { + const lhs_arc = @constCast(&lhs_weak).upgrade(); + defer if (lhs_arc) |l1| if (l1.releaseUnwrap()) |l2| l2.deinit(); + + const rhs_arc = @constCast(&rhs_weak).upgrade(); + defer if (rhs_arc) |r1| if (r1.releaseUnwrap()) |r2| r2.deinit(); + + const lhs = if (lhs_arc) |l| + l.value.* + else + return false; + + const rhs = if (rhs_arc) |r| + r.value.* + else + return false; + if (lhs.item == .container and rhs.item == .element) return true; if (lhs.item == .element and rhs.item == .container) return false; return std.mem.order(u8, lhs.displayName, rhs.displayName) == .lt; @@ -65,6 +81,9 @@ fn resetCurrentItems(self: *@This()) void { // self.current_items.data = null; if (data) |currentItems| { + for (currentItems) |item| { + item.release(); + } self.allocator.free(currentItems); } } @@ -82,4 +101,5 @@ const Tab = @import("../core/tab/tab.zig").Tab; const locked = @import("../core/sync.zig").locked; const AppState = @import("../core/app_state.zig").AppState; const Observer = @import("../core/observable.zig").Observer; +const Arc = @import("zigrc").Arc; const Self = @This(); diff --git a/src/console/main.zig b/src/console/main.zig index 71891e0..c9c5c90 100644 --- a/src/console/main.zig +++ b/src/console/main.zig @@ -124,8 +124,15 @@ const Model = struct { defer vm.app_common_model.current_items.mutex.unlock(); break :blk2 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 children = try ctx.arena.create(std.ArrayList(*vxfw.Text)); + children.* = std.ArrayList(*vxfw.Text).init(ctx.arena); + + // const children = try ctx.arena.alloc(*vxfw.Text, items.len); + for (0.., items) |i, *weak_child| { + const arc_child = weak_child.upgrade() orelse continue; + defer if (arc_child.releaseUnwrap()) |item| item.deinit(); + + const child = arc_child.value.*; const is_active = i == vm.current_items_view.cursor; const fg, const bg = colors: { @@ -162,14 +169,18 @@ const Model = struct { }, }; - children[i] = text_element; + // children[i] = text_element; + try children.append(text_element); } break :blk children; - } else &.{}; + } else { + vm.current_items_view.children.slice = &.{}; + return; + }; }; - const widgets = try ctx.arena.alloc(vxfw.Widget, text_items.len); - for (text_items, 0..) |t, i| { + const widgets = try ctx.arena.alloc(vxfw.Widget, text_items.items.len); + for (text_items.items, 0..) |t, i| { widgets[i] = t.widget(); } diff --git a/src/core/tab/tab.zig b/src/core/tab/tab.zig index b3f6445..d96fa87 100644 --- a/src/core/tab/tab.zig +++ b/src/core/tab/tab.zig @@ -1,17 +1,12 @@ pub const Tab = struct { allocator: std.mem.Allocator, currentLocation: ?*Container, - currentItems: locked(?std.ArrayList(*Item)), + currentItems: locked(?std.ArrayList(Arc(*Item))), currentLocationChanged: Observable(?*Container), currentItemsChanged: bool = false, preCurrentItemsUnload: Observable(*Tab), threadPool: *std.Thread.Pool, rootProvider: *RootProvider, - _private: Private, - - const Private = struct { - currentItemsAllocator: std.heap.ArenaAllocator, - }; pub fn init( self: *Tab, @@ -27,9 +22,6 @@ pub const Tab = struct { .threadPool = threadPool, .rootProvider = rootProvider, .preCurrentItemsUnload = Observable(*Tab).init(allocator), - ._private = .{ - .currentItemsAllocator = std.heap.ArenaAllocator.init(allocator), - }, }; } @@ -70,25 +62,21 @@ pub const Tab = struct { self.preCurrentItemsUnload.notify(self); + const data = self.currentItems.data; 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 arena = self._private.currentItemsAllocator.allocator(); - - var threadSafeAllocator = std.heap.ThreadSafeAllocator{ .child_allocator = arena }; - const allocator = threadSafeAllocator.allocator(); - - errdefer { - _ = self._private.currentItemsAllocator.reset(.free_all); + if (data) |currentItems| { + for (currentItems.items) |*item| { + if (item.releaseUnwrap()) |i| i.deinit(); + } + currentItems.deinit(); + } } { self.currentItems.mutex.lock(); defer self.currentItems.mutex.unlock(); - self.currentItems.data = std.ArrayList(*Item).init(allocator); + self.currentItems.data = std.ArrayList(Arc(*Item)).init(self.allocator); } errdefer { self.currentItems.data.?.deinit(); @@ -101,7 +89,7 @@ pub const Tab = struct { } for (location.children.items) |item| { - const resolvedItem = location.item.provider.getItemByFullName(item, &.{ .skipChildInit = true }, allocator) catch |e| { + const resolvedItem = location.item.provider.getItemByFullName(item, &.{ .skipChildInit = true }, self.allocator) catch |e| { //TODO: save error to container errors std.debug.print("error {} {s}\r\n", .{ e, item.path }); continue; @@ -110,7 +98,9 @@ pub const Tab = struct { self.currentItems.mutex.lock(); defer self.currentItems.mutex.unlock(); - try self.currentItems.data.?.append(resolvedItem); + // const arc = try Arc(*Item).init(self.allocator, resolvedItem); + // try self.currentItems.data.?.append(arc); + try self.currentItems.data.?.append(try Arc(*Item).init(self.allocator, resolvedItem)); } { @@ -124,7 +114,18 @@ pub const Tab = struct { if (self.currentLocation) |c| { c.item.deinit(); } - self._private.currentItemsAllocator.deinit(); + + const data = self.currentItems.data; + self.currentItems.data = null; + if (data) |currentItems| { + for (currentItems.items) |arc_item| { + if (arc_item.releaseUnwrap()) |item| { + item.deinit(); + } + } + currentItems.deinit(); + } + self.allocator.destroy(self); } }; @@ -140,3 +141,4 @@ const Item = models.Item; const locked = @import("../sync.zig").locked; const Observable = @import("../observable.zig").Observable; const RootProvider = @import("../provider/root.zig").RootProvider; +const Arc = @import("zigrc").Arc; diff --git a/src/gui/main.zig b/src/gui/main.zig index bf39e87..926548a 100644 --- a/src/gui/main.zig +++ b/src/gui/main.zig @@ -142,7 +142,12 @@ fn dvui_frame(model: *Model) !void { defer model.core_model.current_items.mutex.unlock(); if (model.core_model.current_items.data) |current_items| { - for (0.., current_items) |i, item| { + for (0.., current_items) |i, *weak_item| { + const arc_item = weak_item.upgrade() orelse continue; + defer if (arc_item.releaseUnwrap()) |item| item.deinit(); + + const item = arc_item.value.*; + const is_active = i == model.selected_item; const fg, const bg = colors: { var fg: dvui.Color = .{ .r = 100, .g = 100, .b = 100 };