simpler std.event.Lock implementation

master
Andrew Kelley 2018-07-31 19:57:46 -04:00
parent 058bfb254c
commit de949b72c7
1 changed files with 2 additions and 25 deletions

View File

@ -106,35 +106,12 @@ pub const Lock = struct {
// will attempt to grab the lock.
_ = @atomicRmw(u8, &self.queue_empty_bit, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst);
while (true) {
const old_bit = @atomicRmw(u8, &self.shared_bit, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
if (old_bit != 0) {
// We did not obtain the lock. Trust that our queue entry will resume us, and allow
// suspend to complete.
break;
}
// We got the lock. However we might have already been resumed from the queue.
const old_bit = @atomicRmw(u8, &self.shared_bit, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
if (old_bit == 0) {
if (self.queue.get()) |node| {
// Whether this node is us or someone else, we tail resume it.
resume node.data;
break;
} else {
// We already got resumed, and there are none left in the queue, which means that
// we aren't even supposed to hold the lock right now.
_ = @atomicRmw(u8, &self.queue_empty_bit, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
_ = @atomicRmw(u8, &self.shared_bit, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst);
// There might be a queue item. If we know the queue is empty, we can be done,
// because the other actor will try to obtain the lock.
// But if there's a queue item, we are the actor which must loop and attempt
// to grab the lock again.
if (@atomicLoad(u8, &self.queue_empty_bit, AtomicOrder.SeqCst) == 1) {
break;
} else {
continue;
}
}
unreachable;
}
}