in src/double-linked-list/doubly_linked_list.cc [353:403]
Status MwCASDList::InsertBefore(DListNode* next, DListNode* node,
bool already_protected) {
if (next == &head_) {
return InsertAfter(next, node, already_protected);
}
EpochGuard guard(GetEpoch(), !already_protected);
// Persist the payload
#ifdef PMEM
NVRAM::Flush(node->payload_size, node->GetPayload());
#endif
while (true) {
RAW_CHECK(((uint64_t)next & kNodeDeleted) == 0, "invalid prev pointer");
auto* prev = ResolveNodePointer(&next->prev, true);
auto* next_next = ResolveNodePointer(&next->next, true);
if (((uint64_t)prev & kNodeDeleted) || (uint64_t)next_next & kNodeDeleted) {
next = GetNext(next, true);
continue;
}
auto* prev_next = ResolveNodePointer(&prev->next, true);
if ((uint64_t)prev_next & kNodeDeleted) {
continue;
}
node->next = next;
node->prev = prev;
#ifdef PMEM
// Persist node
NVRAM::Flush(sizeof(node->prev) + sizeof(node->next), &node->prev);
#endif
RAW_CHECK(MwcTargetField<uint64_t>::IsCleanPtr((uint64_t)prev),
"prev is not normal value");
RAW_CHECK(MwcTargetField<uint64_t>::IsCleanPtr((uint64_t)next),
"next is not normal value");
auto* desc = descriptor_pool_->AllocateDescriptor();
RAW_CHECK(desc, "null MwCAS descriptor");
desc->AddEntry(
(uint64_t*)&node->prev->next, (uint64_t)node->next, (uint64_t)node);
desc->AddEntry(
(uint64_t*)&next->prev, (uint64_t)node->prev, (uint64_t)node);
if(desc->MwCAS()) {
return Status::OK();
}
}
return Status::OK();
}