DVUI

getOrPut

Returns the backing byte slice and a boolean indicating if we found an existing entry

Parameters

#
self:*Data
*Data
gpa:std.mem.Allocator
std.mem.Allocator
key:Key
Key
len:usize
usize
alignment:u8
u8
replace_existing:bool
bool
debug:SavedData.DebugInfo
SavedData.DebugInfo

Source

Implementation

#
pub fn getOrPut(self: *Data, gpa: std.mem.Allocator, key: Key, len: usize, alignment: u8, replace_existing: bool, debug: SavedData.DebugInfo) std.mem.Allocator.Error!struct { []u8, bool } {
    const io = dvui.io;
    self.mutex.lockUncancelable(io);
    defer self.mutex.unlock(io);

    if (replace_existing) try self.trash.ensureUnusedCapacity(gpa, 1);
    const entry = try self.storage.getOrPut(gpa, key);
    errdefer _ = self.storage.remove(key);

    const should_trash = replace_existing and entry.found_existing and entry.value_ptr.data.len != len;
    if (should_trash) {
        // log.debug("dataSet: already had data for id {x} key {s}, freeing previous data\n", .{ id, key });
        if (@TypeOf(debug) != void) {
            if (!debug.eq(entry.value_ptr.debug)) {
                std.debug.panic("Date.getOrPut: stored type {f} doesn't match asked for type {f}", .{ entry.value_ptr.debug, debug });
            }
        }
        self.trash.appendAssumeCapacity(entry.value_ptr.*);
    }
    if (!entry.found_existing or should_trash) {
        entry.value_ptr.* = .{
            .alignment = alignment,
            .data = if (len == 0) &.{} else if (gpa.rawAlloc(len, .fromByteUnits(alignment), @returnAddress())) |ptr| ptr[0..len] else return std.mem.Allocator.Error.OutOfMemory,
            .debug = debug,
        };
    }
    return .{ entry.value_ptr.data, entry.found_existing };
}