コード例 #1
0
    void try_reclaim(node* old_head)
    {
        if (threads_in_pop == 1) {
            // claim list of to-be-deleted nodes
            node* nodes_to_delete = to_be_deleted.exchange(nullptr);

            // are you the only thread in pop()?
            if (!--threads_in_pop) {
                // on other thread can be accessing this list of pending nodes.
                // There may be new pending nodes, but you're not bothered 
                // about them for now, as long as it's safe to reclaim your 
                // list.
                delete_nodes(nodes_to_delete);
            }
            else if (nodes_to_delete) {
                // not safe to reclaim the nodes, so if there are any,
                // you must chain them back onto the list of nodes 
                // pending deletion. 
                // This can happen if there are multiple threads accessing the
                // data structure concurrently. Other threads might have 
                // called pop() in between the first tet of thread_in_pop and
                // the "claiming" of the list, potentially adding new nodes to
                // the list that are still being accesed by one or more of 
                // those other threads.
                chain_pending_nodes(nodes_to_delete);
            }
            delete old_head;
        }
        else {
            // not safe to delete any nodes, add the node to the pending list
            chain_pending_node(old_head);
            --threads_in_pop;
        }
    }
コード例 #2
0
void lock_free_stack<T>::try_reclaim(Node* old_head)
{
    if (threads_in_pop == 1) //единственный в pop() => попытка удалить
    {
        //можно безопасно удалять  только что исключенный из списка old_head
        delete old_head;
        //Пытаемся удалить накопившиеся исключенные узлы
        Node* nodes_to_delete = to_be_deleted.exchange(nullptr); //захватить список на удаление
        if (!--threads_in_pop)//точно единственный?
        {
        //удаляем узлы, накопившиеся в списке  nodes_to_delete
            while(nodes_to_delete)
            {
                Node* next = nodes_to_delete->next;
                delete nodes_to_delete;
                nodes_to_delete = next;
            }
        }
        else if(nodes_to_delete)
        {
            chain_pending_nodes(nodes_to_delete);
        } //если в захваченном списке что-то было, вернуть это в общий список узлов на удаление
    }
    else
    {   //удалять old_head сейчас нельзя => добавим в список для удаления (удалим как-нибудь потом)
        chain_pending_node(old_head);
        --threads_in_pop;
    }
}
 void try_reclaim(node* old_head) { 
     if (1 == threads_in_pop) {
         node* nodes_to_delete = 
             to_be_deleted.exchange(nullptr);
         if (!--threads_in_pop) {
             delete_nodes(nodes_to_delete);
         }
         else if(nodes_to_delete) {
             chain_pending_nodes(nodes_to_delete);
         }
         delete old_head;
     }
     else {
         chain_pending_node(old_head);
         --threads_in_pop;
     }
 }