E6N5WBHRYQKCNE5GDHDO46KKQ3HHGUV7TZLHD63TV3P2PQ65VJGAC
CZRDWLIQAJHD7NDGJYPJ7F7B5SOEJN25WS5U36WVRV7OJ4YZYXEQC
U6AV36GYGP47QDGPPVTLPFIB4KBQKILDSYGW7HIBTIJZNMOYSMNAC
LD2TP6CDUHET2ISQB3P4JOTQTIDDPRLSZJTIYWAO7JTHKUWOF7MQC
NKL44S6YUCLZDH5EDDUJB5BHX2QWDP7SI5RROBVAUXKAU4ADKPAQC
VFO2F37CC2LRTM6PKBCI6654KTSK2AWNGOXF3GYEQGRWDTQCN3RAC
VDX2MMS55XMEHH2TEMOOW225K6NGKB4QXPQFQ2WJLVXJK25BSXMQC
LVNADDHM446QNUHG3VTNBOHNJGCDROOFBVGO4WXMUUAN6Y4LNCNAC
JGESN2Z4ON5VXCCVBUJDKUHFRDI5IFDKGB5FJRKJEYSLM5PQCMEAC
ZXJGCQSAYBMPR75JD2NSK6UX5MD4X7O3BL2VCP6PR4EZCFJKMKXAC
4PPC5BA7ODZF6EAPCOOSQCOVQC3DCTFGBDVBRMQNZP2NVKJCJWPQC
YZHIW6KGNEA34657YJAFI7BWYYRA7KBEX6X6IXA2UDCDMWMRBJPQC
for (0..rlevel + 1) |level| { // +1 because we want to reach rlevel
const pred = preds[level];
const succ = succs[level];
for (0..rlevel + 1) |level| { // +1 because we want to reach rlevel
const pred = preds[level];
const succ = succs[level];
if (pred != prev_pred) { // only count multilayer items once
pred.?.lock.lock();
locks.set(level);
prev_pred = pred;
}
if (pred != prev_pred) { // only count multilayer items once
pred.?.lock.lock();
locks.set(level);
prev_pred = pred;
}
std.debug.assert(pred != null);
// Validation checks that for each layer:
// 1) level ≤ rlevel
// 2) preds[level] and succs[level] are still adjacent at `level`, and
// 3) neither is marked.
// If validation fails, the thread encountered a conflicting operation, so it releases
// the locks it acquired and restarts place finding.
const valid = !pred.?.marked and (succ == null or !succ.?.marked) and
pred.?.nexts[level] == succ;
std.debug.assert(pred != null);
// Validation checks that for each layer:
// 1) level ≤ rlevel
// 2) preds[level] and succs[level] are still adjacent at `level`, and
// 3) neither is marked.
// If validation fails, the thread encountered a conflicting operation, so it releases
// the locks it acquired and restarts place finding.
const valid = !pred.?.marked and (succ == null or !succ.?.marked) and
pred.?.nexts[level] == succ;
// If !valid cleanup and go to PLACE
if (!valid) {
locks.release(&preds);
break :PLACE;
}
// If !valid cleanup and go to FINDNODE
if (!valid) {
locks.release(&preds);
continue :FINDNODE;
// At this point everything is set for adding the new Node.
var node = try Node.init(self.allocator, insert_key, insert_value, rlevel);
// At this point everything is set for adding the new Node.
var node = try Node.init(self.allocator, insert_key, insert_value, rlevel);
NEXT: for (0..node.nexts.len) |level| {
node.nexts[level] = succs[level]; // unlocked, but safe, as not linked yet
preds[level].?.nexts[level] = node;
LEVELS: for (0..node.nexts.len) |level| {
node.nexts[level] = succs[level]; // unlocked, but safe, as not linked yet
preds[level].?.nexts[level] = node;
if (builtin.mode == .Debug) {
// If the next is not null, make sure its key is set
if (node.nexts[level]) |next_node| {
std.debug.assert(next_node.key != null);
}
if (builtin.mode == .Debug) {
// If the next is not null, make sure its key is set
if (node.nexts[level]) |next_node| {
std.debug.assert(next_node.key != null);
}
// Check if all pred nodes were locked when we inserted this node.
var lit = locks.bitset.iterator(.{});
while (lit.next()) |lvl| {
if (preds[lvl].? == preds[level].?) continue :NEXT;
}
@panic("level is not locked...");
// Check if all pred nodes were locked when we inserted this node.
var lit = locks.bitset.iterator(.{});
while (lit.next()) |lvl| {
if (preds[lvl].? == preds[level].?) continue :LEVELS;
// If !valid cleanup and go to PLACE
if (!valid) {
// cleanup the locks
locks.release(&preds);
break :PLACE;
}
// If !valid cleanup and go to FINDNODE
if (!valid) {
// cleanup the locks
locks.release(&preds);
continue :FINDNODE;
// At this point everything is set for removing the Node.
var level: usize = node_delete.nexts.len;
NEXT: while (level > 0) : (level -= 1) {
preds[level - 1].?.nexts[level - 1] = node_delete.nexts[level - 1];
// At this point everything is set for removing the Node.
std.debug.assert(node_delete.?.nexts.len >= 1);
var level: usize = node_delete.?.nexts.len;
LEVELS: while (level > 0) : (level -= 1) {
preds[level - 1].?.nexts[level - 1] = node_delete.?.nexts[level - 1];
if (builtin.mode == .Debug) {
var lit = locks.bitset.iterator(.{});
while (lit.next()) |lvl| {
if (preds[lvl].? == preds[level - 1].?) continue :NEXT;
}
@panic("level is not locked...");
if (builtin.mode == .Debug) {
var lit = locks.bitset.iterator(.{});
while (lit.next()) |lvl| {
if (preds[lvl].? == preds[level - 1].?) continue :LEVELS;