in src/clds_hazard_pointers.c [495:577]
CLDS_HAZARD_POINTER_RECORD_HANDLE clds_hazard_pointers_acquire(CLDS_HAZARD_POINTERS_THREAD_HANDLE clds_hazard_pointers_thread, void* node)
{
CLDS_HAZARD_POINTER_RECORD_HANDLE result;
if (clds_hazard_pointers_thread == NULL)
{
LogError("Invalid arguments: CLDS_HAZARD_POINTERS_THREAD_HANDLE clds_hazard_pointers_thread=%p, void* node=%p",
clds_hazard_pointers_thread, node);
result = NULL;
}
else
{
bool restart_needed;
CLDS_HAZARD_POINTER_RECORD_HANDLE hazard_ptr;
// get a hazard pointer for the node from the free list
do
{
hazard_ptr = interlocked_compare_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers_thread->free_pointers, NULL, NULL);
if (hazard_ptr != NULL)
{
if (interlocked_compare_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers_thread->free_pointers, hazard_ptr->next, hazard_ptr) != hazard_ptr)
{
restart_needed = true;
}
else
{
// got it
restart_needed = false;
}
}
else
{
// no free one
restart_needed = false;
}
}
while (restart_needed);
if (hazard_ptr == NULL)
{
// no more pointers in free list, create one
hazard_ptr = malloc(sizeof(CLDS_HAZARD_POINTER_RECORD));
if (hazard_ptr == NULL)
{
LogError("Error allocating hazard pointer");
result = NULL;
}
else
{
CLDS_HAZARD_POINTER_RECORD* current_list_head;
// add it to the hazard pointer list
current_list_head = interlocked_compare_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers_thread->pointers, NULL, NULL);
(void)interlocked_exchange_pointer(&hazard_ptr->node, node);
hazard_ptr->next = current_list_head;
(void)interlocked_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers_thread->pointers, hazard_ptr);
// inserted in the used hazard pointer list, we are done
result = hazard_ptr;
}
}
else
{
CLDS_HAZARD_POINTER_RECORD* current_list_head;
// add it to the hazard pointer list
current_list_head = interlocked_compare_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers_thread->pointers, NULL, NULL);
(void)interlocked_exchange_pointer(&hazard_ptr->node, node);
hazard_ptr->next = current_list_head;
(void)interlocked_exchange_pointer((void* volatile_atomic*)&clds_hazard_pointers_thread->pointers, hazard_ptr);
// inserted in the used hazard pointer list, we are done
result = hazard_ptr;
}
}
return result;
}