in src/double-linked-list/doubly_linked_list.cc [98:155]
Status CASDList::InsertBefore(DListNode* next, DListNode* node, bool) {
RAW_CHECK(!((uint64_t)next & kNodeDeleted), "invalid next pointer state");
#ifdef PMEM
RAW_CHECK(!((uint64_t)node & kDirtyFlag), "dirty node pointer");
RAW_CHECK(!((uint64_t)next & kDirtyFlag), "dirty next pointer");
#endif
if (next == &head_) {
return InsertAfter(next, node);
}
DListNode* prev = nullptr;
// Persist the payload
#ifdef PMEM
NVRAM::Flush(node->payload_size, node->GetPayload());
#endif
while (true) {
prev = DereferenceNodePointer(&next->prev);
// If the guy supposed to be behind me got deleted, fast
// forward to its next node and retry
#ifdef PMEM
auto* next_next = ReadPersist(&next->next);
#else
auto* next_next = next->next;
#endif
if ((uint64_t)next_next & kNodeDeleted) {
next = GetNext(next);
#ifdef PMEM
RAW_CHECK(!((uint64_t)next & kDirtyFlag), "dirty next pointer");
#endif
prev = CorrectPrev(prev, next); // using the new next
#ifdef PMEM
RAW_CHECK(!((uint64_t)prev & kDirtyFlag), "dirty prev pointer");
#endif
continue;
}
node->prev = (DListNode*)((uint64_t)prev & ~kNodeDeleted);
node->next = (DListNode*)((uint64_t)next & ~kNodeDeleted);
#ifdef PMEM
// Flush node.prev and node.next before installing
NVRAM::Flush(sizeof(node->prev) + sizeof(node->next), &node->prev);
#endif
// Install [node] on prev->next
DListNode* expected = (DListNode*)((uint64_t)next & ~kNodeDeleted);
if (expected == CompareExchange64Ptr(&prev->next, node, expected)) {
break;
}
// Failed, get a new hopefully-correct prev
prev = CorrectPrev(prev, next);
backoff();
}
RAW_CHECK(prev, "invalid prev pointer");
CorrectPrev(prev, next);
return Status::OK();
}