std::shared_ptr<T> pop() { std::atomic<void*>& hp = get_hazard_pointer_for_current_thread(); node* old_head = head.load(); do { node* temp; do { // loop until you've set the harzard pointer to head temp = old_head; hp.store(old_head); old_head = head.load(); } while (old_head != temp); } while (old_head && !head.compare_exchange_strong(old_head, old_head->next)); hp.store(nullptr); // clear hazard pointer once you're finished std::shared_ptr<T> res; if (old_head) { res.swap(old_head->data); if (outstanding_hazard_pointers_for(old_head)) { // check for hazard pointers referencing // a node before you delete it reclaim_later(old_head); } else { delete old_head; } delete_nodes_with_no_hazards(); } return res; }
std::shared_ptr<T> pop() { // get the hazard pointers for the current thread std::atomic<void*>& hp=get_hazard_pointer_for_current_thread(); node* old_head=head.load(); do { node* temp; do { temp=old_head; // store old_head in the hazard pointer hp.store(old_head); old_head=head.load(); } while(old_head!=temp); } // check old_head before deleting. while(old_head && !head.compare_exchange_strong(old_head,old_head->next)); hp.store(nullptr); std::shared_ptr<T> res; if(old_head) { res.swap(old_head->data); if(outstanding_hazard_pointers_for(old_head)) { // old head being accessed by other threads. // add to reclaim later list reclaim_later(old_head); } else { delete old_head; } // traverse through the reclaim later list and delete nodes which are not hazardous. delete_nodes_with_no_hazards(); } return res; }