void IoTHubClientCore_Destroy()

in iothub_client/src/iothub_client_core.c [1223:1380]


void IoTHubClientCore_Destroy(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle)
{
    if (iotHubClientHandle != NULL)
    {
        bool joinClientThread;
        bool joinTransportThread;
        size_t vector_size;

        IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle;

        if (iotHubClientInstance->TransportHandle != NULL)
        {
            joinTransportThread = IoTHubTransport_SignalEndWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle);
        }
        else
        {
            joinTransportThread = false;
        }

        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
        {
            LogError("unable to Lock - - will still proceed to try to end the thread without locking");
        }

        if (iotHubClientInstance->ThreadHandle != NULL)
        {
            iotHubClientInstance->StopThread = 1;
            joinClientThread = true;
        }
        else
        {
            joinClientThread = false;
        }

        if (Unlock(iotHubClientInstance->LockHandle) != LOCK_OK)
        {
            LogError("unable to Unlock");
        }

        if (joinClientThread == true)
        {
            int res;
            if (ThreadAPI_Join(iotHubClientInstance->ThreadHandle, &res) != THREADAPI_OK)
            {
                LogError("ThreadAPI_Join failed");
            }
        }

        if (joinTransportThread == true)
        {
            IoTHubTransport_JoinWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle);
        }

        if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
        {
            LogError("unable to Lock - - will still proceed to try to end the thread without locking");
        }

        /*wait for all uploading threads to finish*/
        while (singlylinkedlist_get_head_item(iotHubClientInstance->httpWorkerThreadInfoList) != NULL)
        {
            // Sleep between runs of the garbage collector in order to give the httpWorker threads time to execute.
            // Otherwise we end up in a spin loop here.
            unsigned int sleeptime_in_ms = (unsigned int)iotHubClientInstance->do_work_freq_ms;
            Unlock(iotHubClientInstance->LockHandle);

            ThreadAPI_Sleep(sleeptime_in_ms);

            if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
            {
                LogError("unable to Lock - - will still proceed to try to end the thread without locking");
            }

            garbageCollectorImpl(iotHubClientInstance);
        }

        if (iotHubClientInstance->httpWorkerThreadInfoList != NULL)
        {
            singlylinkedlist_destroy(iotHubClientInstance->httpWorkerThreadInfoList);
        }

        IoTHubClientCore_LL_Destroy(iotHubClientInstance->IoTHubClientLLHandle);

        if (Unlock(iotHubClientInstance->LockHandle) != LOCK_OK)
        {
            LogError("unable to Unlock");
        }

        vector_size = VECTOR_size(iotHubClientInstance->saved_user_callback_list);
        size_t index = 0;
        for (index = 0; index < vector_size; index++)
        {
            USER_CALLBACK_INFO* queue_cb_info = (USER_CALLBACK_INFO*)VECTOR_element(iotHubClientInstance->saved_user_callback_list, index);
            if (queue_cb_info != NULL)
            {
                if ((queue_cb_info->type == CALLBACK_TYPE_DEVICE_METHOD) || (queue_cb_info->type == CALLBACK_TYPE_INBOUND_DEVICE_METHOD))
                {
                    STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name);
                    BUFFER_delete(queue_cb_info->iothub_callback.method_cb_info.payload);
                }
                else if (queue_cb_info->type == CALLBACK_TYPE_DEVICE_TWIN)
                {
                    if (queue_cb_info->iothub_callback.dev_twin_cb_info.userCallback)
                    {
                        queue_cb_info->iothub_callback.dev_twin_cb_info.userCallback(
                            queue_cb_info->iothub_callback.dev_twin_cb_info.update_state,
                            queue_cb_info->iothub_callback.dev_twin_cb_info.payLoad,
                            queue_cb_info->iothub_callback.dev_twin_cb_info.size,
                            queue_cb_info->iothub_callback.dev_twin_cb_info.userContext
                        );
                    }

                    if (queue_cb_info->iothub_callback.dev_twin_cb_info.payLoad != NULL)
                    {
                        free(queue_cb_info->iothub_callback.dev_twin_cb_info.payLoad);
                    }
                }
                else if (queue_cb_info->type == CALLBACK_TYPE_EVENT_CONFIRM)
                {
                    if (queue_cb_info->iothub_callback.event_confirm_cb_info.eventConfirmationCallback)
                    {
                        queue_cb_info->iothub_callback.event_confirm_cb_info.eventConfirmationCallback(queue_cb_info->iothub_callback.event_confirm_cb_info.confirm_result, queue_cb_info->userContextCallback);
                    }
                }
                else if (queue_cb_info->type == CALLBACK_TYPE_REPORTED_STATE)
                {
                    if (queue_cb_info->iothub_callback.reported_state_cb_info.reportedStateCallback)
                    {
                        queue_cb_info->iothub_callback.reported_state_cb_info.reportedStateCallback(queue_cb_info->iothub_callback.reported_state_cb_info.status_code, queue_cb_info->userContextCallback);
                    }
                }
            }
        }
        VECTOR_destroy(iotHubClientInstance->saved_user_callback_list);

        if (iotHubClientInstance->TransportHandle == NULL)
        {
            Lock_Deinit(iotHubClientInstance->LockHandle);
        }
        if (iotHubClientInstance->devicetwin_user_context != NULL)
        {
            free(iotHubClientInstance->devicetwin_user_context);
        }
        if (iotHubClientInstance->connection_status_user_context != NULL)
        {
            free(iotHubClientInstance->connection_status_user_context);
        }
        if (iotHubClientInstance->message_user_context != NULL)
        {
            free(iotHubClientInstance->message_user_context);
        }
        if (iotHubClientInstance->method_user_context != NULL)
        {
            free(iotHubClientInstance->method_user_context);
        }
        free(iotHubClientInstance);
    }
}