Status MwCASDList::InsertBefore()

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();
}