in linux/src/completion_port_linux.c [266:317]
void completion_port_dec_ref(COMPLETION_PORT_HANDLE completion_port)
{
// Codes_SRS_COMPLETION_PORT_LINUX_11_008: [ If completion_port is NULL, completion_port_dec_ref shall return. ]
if (completion_port == NULL)
{
LogError("Invalid arguments: COMPLETION_PORT_HANDLE completion_port=%p", completion_port);
}
else
{
// Codes_SRS_COMPLETION_PORT_LINUX_11_009: [ completion_port_dec_ref shall decrement the reference count for completion_port. ]
if (DEC_REF(COMPLETION_PORT, completion_port) == 0)
{
// Codes_SRS_COMPLETION_PORT_LINUX_11_012: [ - increment the flag signaling that the threads can complete. ]
(void)interlocked_increment(&completion_port->worker_thread_continue);
// Codes_SRS_COMPLETION_PORT_LINUX_11_010: [ If the reference count reaches 0, completion_port_dec_ref shall do the following: ]
int32_t value;
// Codes_SRS_COMPLETION_PORT_LINUX_11_011: [ wait for the ongoing call count to reach zero. ]
while ((value = interlocked_add(&completion_port->pending_calls, 0)) != 0)
{
(void)wait_on_address(&completion_port->pending_calls, value, UINT32_MAX);
}
// Codes_SRS_COMPLETION_PORT_LINUX_11_013: [ close the epoll object. ]
if (close(completion_port->epoll) != 0)
{
LogErrorNo("failure closing epoll");
}
int dont_care;
// Codes_SRS_COMPLETION_PORT_LINUX_11_014: [ close the thread by calling ThreadAPI_Join. ]
if (ThreadAPI_Join(completion_port->thread_handle, &dont_care) != THREADAPI_OK)
{
LogError("Failure joining thread");
}
// Codes_SRS_COMPLETION_PORT_LINUX_11_015: [ then the memory associated with completion_port shall be freed. ]
PS_LIST_ENTRY entry;
while ((entry = s_list_remove_head(&completion_port->alloc_data_list)) != &completion_port->alloc_data_list)
{
EPOLL_THREAD_DATA* epoll_data = CONTAINING_RECORD(entry, EPOLL_THREAD_DATA, link);
free(epoll_data);
}
REFCOUNT_TYPE_DESTROY(COMPLETION_PORT, completion_port);
}
else
{
// do nothing
}
}
}