144 lines
4.6 KiB
Zig
144 lines
4.6 KiB
Zig
pub const Tab = struct {
|
|
allocator: std.mem.Allocator,
|
|
currentLocation: ?*Container,
|
|
currentItems: locked(?std.ArrayList(*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,
|
|
threadPool: *std.Thread.Pool,
|
|
rootProvider: *RootProvider,
|
|
allocator: std.mem.Allocator,
|
|
) void {
|
|
self.* = Tab{
|
|
.allocator = allocator,
|
|
.currentItems = .{ .data = null },
|
|
.currentLocationChanged = Observable(?*Container).init(allocator),
|
|
.currentLocation = null,
|
|
.threadPool = threadPool,
|
|
.rootProvider = rootProvider,
|
|
.preCurrentItemsUnload = Observable(*Tab).init(allocator),
|
|
._private = .{
|
|
.currentItemsAllocator = std.heap.ArenaAllocator.init(allocator),
|
|
},
|
|
};
|
|
}
|
|
|
|
pub fn setCurrentLocation(self: *Tab, newLocationFullName: models.FullName) !void {
|
|
if (self.currentLocation) |c| {
|
|
c.item.deinit();
|
|
}
|
|
|
|
errdefer {
|
|
self.currentLocation = null;
|
|
self.currentLocationChanged.notify(null);
|
|
}
|
|
|
|
const newLocation = try self.rootProvider.getItemByFullName(newLocationFullName, &.{}, self.allocator);
|
|
errdefer {
|
|
newLocation.deinit();
|
|
}
|
|
|
|
const newLocationContainer = switch (newLocation.item) {
|
|
.container => |c| c,
|
|
.element => return error.NotContainer,
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
fn loadItemsWrapper(self: *Tab, location: *Container) void {
|
|
loadItems(self, location) catch return;
|
|
}
|
|
fn loadItems(self: *Tab, location: *Container) !void {
|
|
{
|
|
self.currentItems.mutex.lock();
|
|
defer self.currentItems.mutex.unlock();
|
|
|
|
self.preCurrentItemsUnload.notify(self);
|
|
|
|
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);
|
|
}
|
|
|
|
{
|
|
self.currentItems.mutex.lock();
|
|
defer self.currentItems.mutex.unlock();
|
|
|
|
self.currentItems.data = std.ArrayList(*Item).init(allocator);
|
|
}
|
|
errdefer {
|
|
self.currentItems.data.?.deinit();
|
|
self.currentItems.data = null;
|
|
}
|
|
|
|
//TODO: add async
|
|
while (location.childrenLoading) {
|
|
std.Thread.sleep(1 * std.time.ns_per_ms);
|
|
}
|
|
|
|
for (location.children.items) |item| {
|
|
const resolvedItem = location.item.provider.getItemByFullName(item, &.{ .skipChildInit = true }, allocator) catch |e| {
|
|
//TODO: save error to container errors
|
|
std.debug.print("error {} {s}\r\n", .{ e, item.path });
|
|
continue;
|
|
};
|
|
|
|
self.currentItems.mutex.lock();
|
|
defer self.currentItems.mutex.unlock();
|
|
|
|
try self.currentItems.data.?.append(resolvedItem);
|
|
}
|
|
|
|
{
|
|
self.currentItems.mutex.lock();
|
|
defer self.currentItems.mutex.unlock();
|
|
self.currentItemsChanged = true;
|
|
}
|
|
std.debug.print("\nASDX\n", .{});
|
|
}
|
|
|
|
pub fn deinit(self: *Tab) void {
|
|
if (self.currentLocation) |c| {
|
|
c.item.deinit();
|
|
}
|
|
self._private.currentItemsAllocator.deinit();
|
|
}
|
|
};
|
|
|
|
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const Mutex = std.Thread.Mutex;
|
|
|
|
const models = @import("../models.zig");
|
|
const Container = models.Container;
|
|
const Item = models.Item;
|
|
|
|
const locked = @import("../sync.zig").locked;
|
|
const Observable = @import("../observable.zig").Observable;
|
|
const RootProvider = @import("../provider/root.zig").RootProvider;
|