const std = @import("std");
const SkipList = @import("lib.zig");
const MY_SIZE = 1000;
pub fn SkipQueue(comptime T: anytype) type {
if (!@hasField(T, "key")) @compileError("must contain 'key' member");
if (!@hasField(T, "value")) @compileError("must contain 'value' member");
const K = blk: {
switch (@typeInfo(T)) {
.Struct => |str_info| {
for (str_info.fields) |field| {
if (std.mem.eql(u8, field.name, "key")) {
break :blk field.field_type;
}
}
},
else => unreachable,
}
};
const V = blk: {
switch (@typeInfo(T)) {
.Struct => |str_info| {
for (str_info.fields) |field| {
if (std.mem.eql(u8, field.name, "value")) {
break :blk field.field_type;
}
}
},
else => unreachable,
}
};
return struct {
skiplist: SkipList.Lazy(K, V, {}, std.sort.asc(K)),
pub fn init(allocator: std.mem.Allocator) !@This() {
var sq: @This() = undefined;
sq.skiplist = try SkipList.Lazy(K, V, {}, comptime std.sort.asc(K))
.init(allocator, SkipList.DEFAULT_SKIP_SIZE, MY_SIZE);
return sq;
}
pub fn deinit(self: @This()) void {
self.skiplist.deinit();
}
pub fn add(self: *@This(), item: T) !void {
_ = try self.skiplist.insert(item.key, item.value);
}
pub fn remove(self: *@This()) !?T {
var ret: ?T = null;
var curr = self.skiplist.head;
while (curr.nexts[0]) |item| : (curr = curr.nexts[0].?) {
const held = item.lock.acquire();
defer held.release();
// already marked for deletion
if (item.marked) continue;
item.marked = true;
ret = .{ .key = item.key.?, .value = item.value };
break;
}
if (ret != null) {
_ = try self.skiplist.remove(ret.?.key);
}
return ret;
}
};
}