/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #undef LOG_TAG #define LOG_TAG "NFC_LIST" bool listInit(listHead* pList) { pList->pFirst = NULL; if(pthread_mutex_init(&pList->mutex, NULL) == -1) { ALOGE("Mutex creation failed (errno=0x%08x)", errno); return false; } return true; } bool listDestroy(listHead* pList) { bool bListNotEmpty = true; while (bListNotEmpty) { bListNotEmpty = listGetAndRemoveNext(pList, NULL); } if(pthread_mutex_destroy(&pList->mutex) == -1) { ALOGE("Mutex destruction failed (errno=0x%08x)", errno); return false; } return true; } bool listAdd(listHead* pList, void* pData) { struct listNode* pNode; struct listNode* pLastNode; bool result; /* Create node */ pNode = (struct listNode*)malloc(sizeof(listNode)); if (pNode == NULL) { result = false; ALOGE("Failed to malloc"); goto clean_and_return; } TRACE("Allocated node: %8p (%8p)", pNode, pData); pNode->pData = pData; pNode->pNext = NULL; pthread_mutex_lock(&pList->mutex); /* Add the node to the list */ if (pList->pFirst == NULL) { /* Set the node as the head */ pList->pFirst = pNode; } else { /* Seek to the end of the list */ pLastNode = pList->pFirst; while(pLastNode->pNext != NULL) { pLastNode = pLastNode->pNext; } /* Add the node to the current list */ pLastNode->pNext = pNode; } result = true; clean_and_return: pthread_mutex_unlock(&pList->mutex); return result; } bool listRemove(listHead* pList, void* pData) { struct listNode* pNode; struct listNode* pRemovedNode; bool result; pthread_mutex_lock(&pList->mutex); if (pList->pFirst == NULL) { /* Empty list */ ALOGE("Failed to deallocate (list empty)"); result = false; goto clean_and_return; } pNode = pList->pFirst; if (pList->pFirst->pData == pData) { /* Get the removed node */ pRemovedNode = pNode; /* Remove the first node */ pList->pFirst = pList->pFirst->pNext; } else { while (pNode->pNext != NULL) { if (pNode->pNext->pData == pData) { /* Node found ! */ break; } pNode = pNode->pNext; } if (pNode->pNext == NULL) { /* Node not found */ result = false; ALOGE("Failed to deallocate (not found %8p)", pData); goto clean_and_return; } /* Get the removed node */ pRemovedNode = pNode->pNext; /* Remove the node from the list */ pNode->pNext = pNode->pNext->pNext; } /* Deallocate the node */ TRACE("Deallocating node: %8p (%8p)", pRemovedNode, pRemovedNode->pData); free(pRemovedNode); result = true; clean_and_return: pthread_mutex_unlock(&pList->mutex); return result; } bool listGetAndRemoveNext(listHead* pList, void** ppData) { struct listNode* pNode; bool result; pthread_mutex_lock(&pList->mutex); if (pList->pFirst) { /* Empty list */ ALOGE("Failed to deallocate (list empty)"); result = false; goto clean_and_return; } /* Work on the first node */ pNode = pList->pFirst; /* Return the data */ if (ppData != NULL) { *ppData = pNode->pData; } /* Remove and deallocate the node */ pList->pFirst = pNode->pNext; TRACE("Deallocating node: %8p (%8p)", pNode, pNode->pData); free(pNode); result = true; clean_and_return: listDump(pList); pthread_mutex_unlock(&pList->mutex); return result; } void listDump(listHead* pList) { struct listNode* pNode = pList->pFirst; TRACE("Node dump:"); while (pNode != NULL) { TRACE("- %8p (%8p)", pNode, pNode->pData); pNode = pNode->pNext; } }