fix: don't leak buffer names when deleting buffers
This commit also refactors the Buffer.Manager to make similar issues easier to avoid in future.
This commit is contained in:
parent
f201728457
commit
22e36481d6
2 changed files with 35 additions and 36 deletions
|
@ -24,12 +24,27 @@ pub fn deinit(self: *Self) void {
|
||||||
self.buffers.deinit(self.allocator);
|
self.buffers.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_buffer(self: *const Self, file_path: []const u8) ?*Buffer {
|
||||||
|
return self.buffers.get(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_buffer(self: *Self, buffer: *Buffer) error{OutOfMemory}!void {
|
||||||
|
try self.buffers.put(self.allocator, try self.allocator.dupe(u8, buffer.get_file_path()), buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_buffer(self: *Self, buffer: *Buffer) void {
|
||||||
|
if (self.buffers.fetchRemove(buffer.get_file_path())) |kv| {
|
||||||
|
self.allocator.free(kv.key);
|
||||||
|
kv.value.deinit();
|
||||||
|
} else buffer.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_file(self: *Self, file_path: []const u8) Buffer.LoadFromFileError!*Buffer {
|
pub fn open_file(self: *Self, file_path: []const u8) Buffer.LoadFromFileError!*Buffer {
|
||||||
const buffer = if (self.buffers.get(file_path)) |buffer| buffer else blk: {
|
const buffer = if (self.get_buffer(file_path)) |buffer| buffer else blk: {
|
||||||
var buffer = try Buffer.create(self.allocator);
|
var buffer = try Buffer.create(self.allocator);
|
||||||
errdefer buffer.deinit();
|
errdefer buffer.deinit();
|
||||||
try buffer.load_from_file_and_update(file_path);
|
try buffer.load_from_file_and_update(file_path);
|
||||||
try self.buffers.put(self.allocator, try self.allocator.dupe(u8, file_path), buffer);
|
try self.add_buffer(buffer);
|
||||||
break :blk buffer;
|
break :blk buffer;
|
||||||
};
|
};
|
||||||
buffer.update_last_used_time();
|
buffer.update_last_used_time();
|
||||||
|
@ -43,7 +58,7 @@ pub fn open_scratch(self: *Self, file_path: []const u8, content: []const u8) Buf
|
||||||
errdefer buffer.deinit();
|
errdefer buffer.deinit();
|
||||||
try buffer.load_from_string_and_update(file_path, content);
|
try buffer.load_from_string_and_update(file_path, content);
|
||||||
buffer.file_exists = true;
|
buffer.file_exists = true;
|
||||||
try self.buffers.put(self.allocator, try self.allocator.dupe(u8, file_path), buffer);
|
try self.add_buffer(buffer);
|
||||||
break :blk buffer;
|
break :blk buffer;
|
||||||
};
|
};
|
||||||
buffer.update_last_used_time();
|
buffer.update_last_used_time();
|
||||||
|
@ -75,20 +90,13 @@ pub fn extract_state(self: *Self, iter: *[]const u8) !void {
|
||||||
buffer.deinit();
|
buffer.deinit();
|
||||||
}
|
}
|
||||||
try buffer.extract_state(iter);
|
try buffer.extract_state(iter);
|
||||||
try self.buffers.put(self.allocator, try self.allocator.dupe(u8, buffer.get_file_path()), buffer);
|
try self.add_buffer(buffer);
|
||||||
tp.trace(tp.channel.debug, .{ "buffer", "extract", buffer.get_file_path(), buffer.file_type_name });
|
tp.trace(tp.channel.debug, .{ "buffer", "extract", buffer.get_file_path(), buffer.file_type_name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_buffer_for_file(self: *const Self, file_path: []const u8) ?*Buffer {
|
pub fn get_buffer_for_file(self: *const Self, file_path: []const u8) ?*Buffer {
|
||||||
return self.buffers.get(file_path);
|
return self.get_buffer(file_path);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete_buffer(self: *Self, file_path: []const u8) bool {
|
|
||||||
const buffer = self.buffers.get(file_path) orelse return false;
|
|
||||||
const did_remove = self.buffers.remove(file_path);
|
|
||||||
buffer.deinit();
|
|
||||||
return did_remove;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn retire(_: *Self, buffer: *Buffer, meta: ?[]const u8) void {
|
pub fn retire(_: *Self, buffer: *Buffer, meta: ?[]const u8) void {
|
||||||
|
@ -100,10 +108,8 @@ pub fn retire(_: *Self, buffer: *Buffer, meta: ?[]const u8) void {
|
||||||
pub fn close_buffer(self: *Self, buffer: *Buffer) void {
|
pub fn close_buffer(self: *Self, buffer: *Buffer) void {
|
||||||
buffer.hidden = true;
|
buffer.hidden = true;
|
||||||
tp.trace(tp.channel.debug, .{ "buffer", "close", buffer.get_file_path(), "hidden", buffer.hidden, "ephemeral", buffer.ephemeral });
|
tp.trace(tp.channel.debug, .{ "buffer", "close", buffer.get_file_path(), "hidden", buffer.hidden, "ephemeral", buffer.ephemeral });
|
||||||
if (buffer.is_ephemeral()) {
|
if (buffer.is_ephemeral())
|
||||||
_ = self.buffers.remove(buffer.get_file_path());
|
self.delete_buffer(buffer);
|
||||||
buffer.deinit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_most_recently_used(self: *Self, allocator: std.mem.Allocator) error{OutOfMemory}![]*Buffer {
|
pub fn list_most_recently_used(self: *Self, allocator: std.mem.Allocator) error{OutOfMemory}![]*Buffer {
|
||||||
|
@ -148,7 +154,7 @@ pub fn count_dirty_buffers(self: *const Self) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_buffer_dirty(self: *const Self, file_path: []const u8) bool {
|
pub fn is_buffer_dirty(self: *const Self, file_path: []const u8) bool {
|
||||||
return if (self.buffers.get(file_path)) |buffer| buffer.is_dirty() else false;
|
return if (self.get_buffer(file_path)) |buffer| buffer.is_dirty() else false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_all(self: *const Self) Buffer.StoreToFileError!void {
|
pub fn save_all(self: *const Self) Buffer.StoreToFileError!void {
|
||||||
|
@ -183,45 +189,38 @@ pub fn delete_all(self: *Self) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_others(self: *Self, protected: *Buffer) error{OutOfMemory}!void {
|
pub fn delete_others(self: *Self, protected: *Buffer) error{OutOfMemory}!void {
|
||||||
var keys = try std.ArrayList(*[]const u8).initCapacity(self.allocator, self.buffers.size);
|
var to_delete = try std.ArrayList(*Buffer).initCapacity(self.allocator, self.buffers.size);
|
||||||
defer keys.deinit(self.allocator);
|
defer to_delete.deinit(self.allocator);
|
||||||
|
|
||||||
var it = self.buffers.iterator();
|
var it = self.buffers.iterator();
|
||||||
|
|
||||||
while (it.next()) |p| {
|
while (it.next()) |p| {
|
||||||
const buffer = p.value_ptr.*;
|
const buffer = p.value_ptr.*;
|
||||||
if (buffer != protected) {
|
if (buffer != protected)
|
||||||
try keys.append(self.allocator, p.key_ptr);
|
to_delete.appendAssumeCapacity(buffer);
|
||||||
}
|
|
||||||
}
|
|
||||||
for (keys.items) |k| {
|
|
||||||
const buffer = self.buffers.get(k.*) orelse continue;
|
|
||||||
_ = self.buffers.remove(k.*);
|
|
||||||
buffer.deinit();
|
|
||||||
}
|
}
|
||||||
|
for (to_delete.items) |buffer|
|
||||||
|
_ = self.delete_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_others(self: *Self, protected: *Buffer) error{OutOfMemory}!usize {
|
pub fn close_others(self: *Self, protected: *Buffer) error{OutOfMemory}!usize {
|
||||||
var remaining: usize = 0;
|
var remaining: usize = 0;
|
||||||
var keys = try std.ArrayList(*[]const u8).initCapacity(self.allocator, self.buffers.size);
|
var to_delete = try std.ArrayList(*Buffer).initCapacity(self.allocator, self.buffers.size);
|
||||||
defer keys.deinit(self.allocator);
|
defer to_delete.deinit(self.allocator);
|
||||||
|
|
||||||
var it = self.buffers.iterator();
|
var it = self.buffers.iterator();
|
||||||
while (it.next()) |p| {
|
while (it.next()) |p| {
|
||||||
const buffer = p.value_ptr.*;
|
const buffer = p.value_ptr.*;
|
||||||
if (buffer != protected) {
|
if (buffer != protected) {
|
||||||
if (buffer.is_ephemeral() or !buffer.is_dirty()) {
|
if (buffer.is_ephemeral() or !buffer.is_dirty()) {
|
||||||
try keys.append(self.allocator, p.key_ptr);
|
to_delete.appendAssumeCapacity(buffer);
|
||||||
} else {
|
} else {
|
||||||
remaining += 1;
|
remaining += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (keys.items) |k| {
|
for (to_delete.items) |buffer|
|
||||||
const buffer = self.buffers.get(k.*) orelse continue;
|
self.delete_buffer(buffer);
|
||||||
_ = self.buffers.remove(k.*);
|
|
||||||
buffer.deinit();
|
|
||||||
}
|
|
||||||
return remaining;
|
return remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -632,7 +632,7 @@ const cmds = struct {
|
||||||
return tp.exit("unsaved changes");
|
return tp.exit("unsaved changes");
|
||||||
if (self.get_active_editor()) |editor| if (editor.buffer == buffer)
|
if (self.get_active_editor()) |editor| if (editor.buffer == buffer)
|
||||||
editor.close_file(.{}) catch |e| return e;
|
editor.close_file(.{}) catch |e| return e;
|
||||||
_ = self.buffer_manager.delete_buffer(file_path);
|
self.buffer_manager.delete_buffer(buffer);
|
||||||
const logger = log.logger("buffer");
|
const logger = log.logger("buffer");
|
||||||
defer logger.deinit();
|
defer logger.deinit();
|
||||||
logger.print("deleted buffer {s}", .{file_path});
|
logger.print("deleted buffer {s}", .{file_path});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue