CLDS_SORTED_LIST_GET_ALL_RESULT clds_sorted_list_get_all()

in src/clds_sorted_list.c [1819:1905]


CLDS_SORTED_LIST_GET_ALL_RESULT clds_sorted_list_get_all(CLDS_SORTED_LIST_HANDLE clds_sorted_list, CLDS_HAZARD_POINTERS_THREAD_HANDLE clds_hazard_pointers_thread, uint64_t item_count, CLDS_SORTED_LIST_ITEM** items, uint64_t* retrieved_item_count, bool require_locked_list)
{
    CLDS_SORTED_LIST_GET_ALL_RESULT result;

    if (
        /*Codes_SRS_CLDS_SORTED_LIST_42_041: [ If clds_sorted_list is NULL then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_ERROR. ]*/
        (clds_sorted_list == NULL) ||
        /*Codes_SRS_CLDS_SORTED_LIST_42_042: [ If clds_hazard_pointers_thread is NULL then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_ERROR. ]*/
        (clds_hazard_pointers_thread == NULL) ||
        /*Codes_SRS_CLDS_SORTED_LIST_42_043: [ If item_count is 0 then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_ERROR. ]*/
        (item_count == 0) ||
        /*Codes_SRS_CLDS_SORTED_LIST_42_044: [ If items is NULL then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_ERROR. ]*/
        (items == NULL) ||
        /*Codes_SRS_CLDS_SORTED_LIST_01_095: [ If retrieved_item_count is NULL then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_ERROR. ]*/
        (retrieved_item_count == NULL)
        )
    {
        LogError("Invalid arguments: CLDS_SORTED_LIST_HANDLE clds_sorted_list=%p, CLDS_HAZARD_POINTERS_THREAD_HANDLE clds_hazard_pointers_thread=%p, uint64_t item_count=%" PRIu64 ", CLDS_SORTED_LIST_ITEM** items=%p, uint64_t* retrieved_item_count=%p, bool require_locked_list=%" PRI_BOOL "",
            clds_sorted_list, clds_hazard_pointers_thread, item_count, items, retrieved_item_count, MU_BOOL_VALUE(require_locked_list));
        result = CLDS_SORTED_LIST_GET_ALL_ERROR;
    }
    else
    {
        if (
            require_locked_list &&
            (interlocked_add(&clds_sorted_list->locked_for_write, 0) == 0)
            )
        {
            /*Codes_SRS_CLDS_SORTED_LIST_42_045: [ If require_locked_list is true and the counter to lock the list for writes is 0 then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_NOT_LOCKED. ]*/
            LogError("Must lock the list before getting all items");
            result = CLDS_SORTED_LIST_GET_ALL_NOT_LOCKED;
        }
        else
        {
            /*Codes_SRS_CLDS_SORTED_LIST_42_046: [ For each item in the list: ]*/
            uint64_t current_index = 0;
            CLDS_SORTED_LIST_ITEM* current_item = interlocked_compare_exchange_pointer((void* volatile_atomic*)&clds_sorted_list->head, NULL, NULL);

            while (current_item != NULL)
            {
                CLDS_SORTED_LIST_ITEM* next_item = interlocked_compare_exchange_pointer((void* volatile_atomic*)&current_item->next, NULL, NULL);

                if (current_index + 1 > item_count)
                {
                    /*Codes_SRS_CLDS_SORTED_LIST_42_049: [ If item_count is less than the number of items in the list then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_NOT_ENOUGH_SPACE. ]*/
                    LogError("Attempted to get all items with array of size %" PRIu64 ", but there were at least %" PRIu64 " items in the list (too small)",
                        item_count, current_index + 1);
                    break;
                }

                /*Codes_SRS_CLDS_SORTED_LIST_42_047: [ clds_sorted_list_get_all shall increment the ref count. ]*/
                (void)clds_sorted_list_node_inc_ref(current_item);

                /*Codes_SRS_CLDS_SORTED_LIST_42_048: [ clds_sorted_list_get_all shall store the pointer in items. ]*/
                items[current_index] = current_item;

                current_index++;
                current_item = next_item;
            }

            if (current_item != NULL)
            {
                /*Codes_SRS_CLDS_SORTED_LIST_42_049: [ If item_count is less than the number of items in the list then clds_sorted_list_get_all shall fail and return CLDS_SORTED_LIST_GET_ALL_NOT_ENOUGH_SPACE. ]*/
                LogError("Attempted to get all items with array of size %" PRIu64 ", but there were %" PRIu64 " items in the list (too large)",
                    item_count, current_index);

                for (uint64_t i = 0; i < current_index; ++i)
                {
                    clds_sorted_list_node_release(items[i]);
                    items[i] = NULL;
                }

                result = CLDS_SORTED_LIST_GET_ALL_NOT_ENOUGH_SPACE;
            }
            else
            {
                /*Codes_SRS_CLDS_SORTED_LIST_01_094: [ Otherwise, clds_sorted_list_get_all shall write in retrieved_item_count the number of items copied to items. ] */
                *retrieved_item_count = current_index;

                /*Codes_SRS_CLDS_SORTED_LIST_42_050: [ clds_sorted_list_get_all shall succeed and return CLDS_SORTED_LIST_GET_ALL_OK. ]*/
                result = CLDS_SORTED_LIST_GET_ALL_OK;
            }
        }
    }

    return result;
}