• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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