static void hp_thread_cleanup_func()

in src/clds_hazard_pointers.c [291:344]


static void hp_thread_cleanup_func(void* context)
{
    CLDS_HAZARD_POINTERS_HANDLE clds_hazard_pointers = context;

    // Clean up the inactive threads in case reclaim hasn't been running
    (void)interlocked_increment(&clds_hazard_pointers->pending_reclaim_calls);
    int64_t current_epoch = interlocked_add_64(&clds_hazard_pointers->epoch, 0);
    if (interlocked_decrement(&clds_hazard_pointers->pending_reclaim_calls) == 0)
    {
        if (interlocked_compare_exchange_64(&clds_hazard_pointers->epoch, current_epoch + 1, current_epoch) != current_epoch)
        {
            // epoch already incremented by other thread, let them do the cleanup
        }
        else
        {
            free_inactive_threads_in_previous_epochs(clds_hazard_pointers, current_epoch + 1);
        }
    }

    void* volatile_atomic* current_thread_address = (void* volatile_atomic*)&clds_hazard_pointers->head;
    CLDS_HAZARD_POINTERS_THREAD_HANDLE current_thread = interlocked_compare_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers->head, NULL, NULL);
    while (current_thread != NULL)
    {
        CLDS_HAZARD_POINTERS_THREAD_HANDLE next_thread = interlocked_compare_exchange_pointer((void* volatile_atomic*)&current_thread->next, NULL, NULL);
        if (interlocked_add(&current_thread->active, 0) == 1)
        {
            current_thread_address = (void* volatile_atomic*)&current_thread->next;
            current_thread = next_thread;
        }
        else
        {
            // remove from the list, no longer active
            if (interlocked_compare_exchange_pointer(current_thread_address, next_thread, current_thread) == current_thread)
            {
                // removed, great, we won't see this any longer

                // add it to the inactive threads
                if (add_to_inactive_threads(clds_hazard_pointers, current_thread) != 0)
                {
                    LogCriticalAndTerminate("Too many inactive threads");
                    // should not happen
                }

                // current_thread_address stays the same
                current_thread = next_thread;
            }
            else
            {
                // not removed, changed in the meanwhile, this should not really happen, but we don't care either
                break;
            }
        }
    }
}