1 /*! 2 * \copy 3 * Copyright (c) 2009-2015, Cisco Systems 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * 32 * \file WelsList 33 * 34 * \brief for the list function needed in ThreadPool 35 * 36 * \date 9/27/2015 Created 37 * 38 ************************************************************************************* 39 */ 40 41 42 #ifndef _WELS_LIST_H_ 43 #define _WELS_LIST_H_ 44 45 #include "typedefs.h" 46 #include <stdlib.h> 47 48 namespace WelsCommon { 49 50 template<typename TNodeType> 51 struct SNode { 52 TNodeType* pPointer; 53 SNode* pPrevNode; 54 SNode* pNextNode; 55 }; 56 57 template<typename TNodeType> 58 class CWelsList { 59 public: CWelsList()60 CWelsList() { 61 m_iCurrentNodeCount = 0; 62 m_iMaxNodeCount = 50; 63 64 m_pCurrentList = NULL; 65 m_pFirst = NULL; 66 m_pCurrent = NULL; 67 m_pLast = NULL; 68 }; ~CWelsList()69 ~CWelsList() { 70 if (m_pCurrentList) { 71 free (m_pCurrentList); 72 m_pCurrentList = NULL; 73 } 74 75 m_pCurrentList = NULL; 76 m_pFirst = NULL; 77 m_pCurrent = NULL; 78 m_pLast = NULL; 79 }; 80 size()81 int32_t size() { 82 return m_iCurrentNodeCount; 83 } 84 push_back(TNodeType * pNode)85 bool push_back (TNodeType* pNode) { 86 if (!pNode) { 87 return false; 88 } 89 90 if (NULL == m_pCurrentList) { 91 m_pCurrentList = static_cast<SNode<TNodeType>*> (malloc (m_iMaxNodeCount * sizeof (SNode<TNodeType>))); 92 if (NULL == m_pCurrentList) { 93 return false; 94 } else { 95 ResetStorage(); 96 } 97 } 98 99 if (NULL == m_pCurrent) { 100 if (!ExpandList()) { 101 return false; 102 } 103 } 104 105 m_pCurrent->pPointer = pNode; 106 m_pCurrent = m_pCurrent->pNextNode; 107 m_iCurrentNodeCount++; 108 109 return true; 110 } 111 begin()112 TNodeType* begin() { 113 if (m_pFirst) { 114 return m_pFirst->pPointer; 115 } 116 return NULL; 117 } 118 pop_front()119 void pop_front() { 120 if (m_iCurrentNodeCount == 0) { 121 return; 122 } 123 124 SNode<TNodeType>* pTemp = m_pFirst; 125 126 m_pFirst = m_pFirst->pNextNode; 127 m_pFirst->pPrevNode = NULL; 128 129 CleanOneNode (pTemp); 130 131 m_pLast->pNextNode = pTemp; 132 pTemp->pPrevNode = m_pLast; 133 m_pLast = pTemp; 134 135 if (NULL == m_pCurrent) 136 m_pCurrent = m_pLast; 137 138 m_iCurrentNodeCount --; 139 } 140 erase(TNodeType * pNode)141 bool erase (TNodeType* pNode) { 142 if (0 == m_iCurrentNodeCount) { 143 return false; 144 } 145 146 SNode<TNodeType>* pTemp = m_pFirst; 147 do { 148 if (pNode == pTemp->pPointer) { 149 if (pTemp->pPrevNode) { 150 pTemp->pPrevNode->pNextNode = pTemp->pNextNode; 151 } else { 152 m_pFirst = pTemp->pNextNode; 153 } 154 155 if (pTemp->pNextNode) { 156 pTemp->pNextNode->pPrevNode = pTemp->pPrevNode; 157 } 158 159 CleanOneNode (pTemp); 160 m_iCurrentNodeCount --; 161 162 m_pLast->pNextNode = pTemp; 163 pTemp->pPrevNode = m_pLast; 164 m_pLast = pTemp; 165 166 return true; 167 } 168 169 pTemp = pTemp->pNextNode; 170 171 } while (pTemp && pTemp->pPointer); 172 return false; 173 } 174 findNode(TNodeType * pNodeTarget)175 bool findNode (TNodeType* pNodeTarget) { 176 if ((m_iCurrentNodeCount > 0) && pNodeTarget) { 177 SNode<TNodeType>* pNode = m_pFirst; 178 while (pNode) { 179 if (pNode->pPointer == pNodeTarget) { 180 return true; 181 } 182 pNode = pNode->pNextNode; 183 } 184 } 185 return false; 186 } 187 getNode(int iNodeIdx)188 TNodeType* getNode (int iNodeIdx) { 189 if ((iNodeIdx > m_iCurrentNodeCount - 1) || (0 == m_iCurrentNodeCount)) { 190 return NULL; 191 } 192 SNode<TNodeType>* pNode = m_pFirst; 193 for (int i = 0; i < iNodeIdx; i++) { 194 if (pNode->pNextNode) { 195 pNode = pNode->pNextNode; 196 } else { 197 return NULL; 198 } 199 } 200 return pNode->pPointer; 201 } 202 203 private: ExpandList()204 bool ExpandList() { 205 SNode<TNodeType>* tmpCurrentList = static_cast<SNode<TNodeType>*> (malloc (m_iMaxNodeCount * 2 * sizeof ( 206 SNode<TNodeType>))); 207 if (tmpCurrentList == NULL) { 208 return false; 209 } 210 InitStorage (tmpCurrentList, (m_iMaxNodeCount * 2) - 1); 211 212 SNode<TNodeType>* pTemp = m_pFirst; 213 for (int i = 0; ((i < m_iMaxNodeCount) && pTemp); i++) { 214 tmpCurrentList[i].pPointer = pTemp->pPointer; 215 pTemp = pTemp->pNextNode; 216 } 217 218 free (m_pCurrentList); 219 m_pCurrentList = tmpCurrentList; 220 m_iCurrentNodeCount = m_iMaxNodeCount; 221 m_iMaxNodeCount = m_iMaxNodeCount * 2; 222 m_pFirst = & (m_pCurrentList[0]); 223 m_pLast = & (m_pCurrentList[m_iMaxNodeCount - 1]); 224 m_pCurrent = & (m_pCurrentList[m_iCurrentNodeCount]); 225 return true; 226 } 227 InitStorage(SNode<TNodeType> * pList,const int32_t iMaxIndex)228 void InitStorage (SNode<TNodeType>* pList, const int32_t iMaxIndex) { 229 pList[0].pPrevNode = NULL; 230 pList[0].pPointer = NULL; 231 pList[0].pNextNode = & (pList[1]); 232 for (int i = 1; i < iMaxIndex; i++) { 233 pList[i].pPrevNode = & (pList[i - 1]); 234 pList[i].pPointer = NULL; 235 pList[i].pNextNode = & (pList[i + 1]); 236 } 237 pList[iMaxIndex].pPrevNode = & (pList[iMaxIndex - 1]); 238 pList[iMaxIndex].pPointer = NULL; 239 pList[iMaxIndex].pNextNode = NULL; 240 } 241 242 CleanOneNode(SNode<TNodeType> * pSNode)243 void CleanOneNode (SNode<TNodeType>* pSNode) { 244 pSNode->pPointer = NULL; 245 pSNode->pPrevNode = NULL; 246 pSNode->pNextNode = NULL; 247 } 248 ResetStorage()249 void ResetStorage() { 250 InitStorage (m_pCurrentList, m_iMaxNodeCount - 1); 251 m_pCurrent = m_pCurrentList; 252 m_pFirst = & (m_pCurrentList[0]); 253 m_pLast = & (m_pCurrentList[m_iMaxNodeCount - 1]); 254 } 255 256 private: 257 int32_t m_iCurrentNodeCount; 258 int32_t m_iMaxNodeCount; 259 SNode<TNodeType>* m_pCurrentList; 260 SNode<TNodeType>* m_pFirst; 261 SNode<TNodeType>* m_pLast; 262 SNode<TNodeType>* m_pCurrent; 263 }; 264 265 template<typename TNodeType> 266 class CWelsNonDuplicatedList : public CWelsList<TNodeType> { 267 public: push_back(TNodeType * pNode)268 bool push_back (TNodeType* pNode) { 269 if (0 != this->size()) { 270 if ((NULL != pNode) && (this->findNode (pNode))) { //not checking NULL for easier testing 271 return false; 272 } 273 } 274 275 return CWelsList<TNodeType>::push_back (pNode); 276 } 277 278 }; 279 280 281 } 282 283 284 #endif 285 286 287 288