This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig standard library. Private Function
fnunlock(m: *ParkingMutex) void {
state: switch (State.locked_once) { // assume 'locked_once' to optimize for uncontended case
.unlocked => unreachable, // we hold the lock
.locked_once => continue :statem.state.cmpxchgWeak(
.locked_once,
.unlocked,
.release, // release lock
.acquire, // acquire any `Waiter` memory
) orelse {
@branchHint(.likely);
return;
},
_ => |last_state| {
// The logic here does not have ABA problems, and does some accesses non-atomically,// because `Waiter.next` is owned by the lock holder (that's us!) once the waiter is// in the linked list, up until we unpark the waiter.// Run through the waiter list to the end to ensure fairness. This is obviously not// ideal, but it shouldn't be a big deal in practice provided the critical section// is fairly small (so we won't get too many threads contending the mutex at once).// There's a *chance* we could get away with a LIFO queue for our use case, but I// don't wanna risk that.varparent: ?*Waiter = null;
varwaiter: *Waiter = last_state.waiter().?;
while (waiter.next) |next| {
parent = waiter;
waiter = next;
}
// `waiter` is next in line for the lock. Remove them from the list.if (parent) |p| {
assert(p.next == waiter);
p.next = null;
} else {
// We're waking the last waiter, so clear the list head.if (m.state.cmpxchgWeak(
.fromWaiter(last_state.waiter().?),
.locked_once,
.acquire,
.acquire, // acquire any new `Waiter` memory
)) |new_state| {
continue :statenew_state;
}
}
// Now we're ready to actually hand the lock over to them.consttid = waiter.tid; // load before the unpark below potentially invalidates `waiter`if (need_unpark_flag) setUnparkFlag(&waiter.unpark_flag);
unpark(&.{tid}, m);
return;
},
}
}