ref: a3f606e58a09c371893a1ece7d5d6c5b9eeb10ba
parent: bc566f0923d099531a573220ae7e83056f52da52
author: Sijia Chen <[email protected]>
date: Thu Oct 15 07:17:29 EDT 2015
replacement of std::list for m_cBusyThreads https://rbcommons.com/s/OpenH264/r/1320/
--- a/codec/build/iOS/common/common.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/common/common.xcodeproj/project.pbxproj
@@ -58,6 +58,7 @@
0DD32A911B467C73009181A1 /* WelsThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsThread.h; sourceTree = "<group>"; };
0DD32A921B467C73009181A1 /* WelsThreadPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsThreadPool.h; sourceTree = "<group>"; };
0DD32A931B468F77009181A1 /* WelsThreadPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WelsThreadPool.cpp; sourceTree = "<group>"; };
+ 0DEA477E1BB36FE100ADD134 /* WelsList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsList.h; sourceTree = "<group>"; };
4C3406B218D96EA600DFA14A /* arm_arch_common_macro.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = arm_arch_common_macro.S; sourceTree = "<group>"; };
4C3406B318D96EA600DFA14A /* deblocking_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = deblocking_neon.S; sourceTree = "<group>"; };
4C3406B418D96EA600DFA14A /* expand_picture_neon.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = expand_picture_neon.S; sourceTree = "<group>"; };
@@ -147,6 +148,7 @@
4C3406C118D96EA600DFA14A /* typedefs.h */,
5BA8F2BE19603F3500011CE4 /* wels_common_defs.h */,
0DB71EF31BAB273500EABC51 /* WelsCircleQueue.h */,
+ 0DEA477E1BB36FE100ADD134 /* WelsList.h */,
0DD32A8E1B467B83009181A1 /* WelsLock.h */,
0DD32A8F1B467C73009181A1 /* WelsTask.h */,
0DD32A901B467C73009181A1 /* WelsTaskThread.h */,
--- a/codec/common/inc/WelsCircleQueue.h
+++ b/codec/common/inc/WelsCircleQueue.h
@@ -91,7 +91,6 @@
return true;
}
}
-
}
}
return false;
@@ -121,7 +120,7 @@
m_iCurrentListEnd = 0;
}
if (m_iCurrentListEnd == m_iCurrentListStart) {
- int32_t ret = ExpandList();
+ int32_t ret = ExpandQueue();
if (ret) {
return 1;
}
@@ -129,7 +128,7 @@
return 0;
}
- int32_t ExpandList() {
+ int32_t ExpandQueue() {
TNodeType** tmpCurrentTaskQueue = static_cast<TNodeType**> (malloc (m_iMaxNodeCount * 2 * sizeof (TNodeType*)));
if (tmpCurrentTaskQueue == NULL) {
return 1;
@@ -158,7 +157,6 @@
int32_t m_iMaxNodeCount;
TNodeType** m_pCurrentQueue;
};
-
}
--- /dev/null
+++ b/codec/common/inc/WelsList.h
@@ -1,0 +1,233 @@
+/*!
+ * \copy
+ * Copyright (c) 2009-2015, Cisco Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * \file WelsList
+ *
+ * \brief for the list function needed in ThreadPool
+ *
+ * \date 9/27/2015 Created
+ *
+ *************************************************************************************
+ */
+
+
+#ifndef _WELS_LIST_H_
+#define _WELS_LIST_H_
+
+#include "typedefs.h"
+
+namespace WelsCommon {
+
+template<typename TNodeType>
+struct SNode {
+ TNodeType* pPointer;
+ SNode* pPrevNode;
+ SNode* pNextNode;
+};
+
+template<typename TNodeType>
+class CWelsList {
+ public:
+ CWelsList() {
+ m_iCurrentNodeCount = 0;
+ m_iMaxNodeCount = 50;
+ m_pCurrentList = static_cast<SNode<TNodeType>*> (malloc (m_iMaxNodeCount * sizeof (SNode<TNodeType>)));
+ //here using array storage to simulate list is to avoid the frequent malloc/free of Nodes which may cause fragmented memory
+ ResetStorage();
+ };
+ ~CWelsList() {
+ free (m_pCurrentList);
+ };
+
+ int32_t size() {
+ return m_iCurrentNodeCount;
+ }
+
+ bool push_back (TNodeType* pNode) {
+ m_pCurrent->pPointer = pNode;
+ if (0 == m_iCurrentNodeCount) {
+ m_pFirst = m_pCurrent;
+ }
+
+ m_iCurrentNodeCount++;
+ if (m_iCurrentNodeCount == m_iMaxNodeCount) {
+ if (!ExpandList()) {
+ return false;
+ }
+ }
+
+ SNode<TNodeType>* pNext = FindNextStorage();
+ m_pCurrent->pNextNode = pNext;
+ pNext->pPrevNode = m_pCurrent;
+ m_pCurrent = pNext;
+
+ return true;
+ }
+
+ TNodeType* begin() {
+ if (m_pFirst) {
+ return m_pFirst->pPointer;
+ }
+ return NULL;
+ }
+
+ void pop_front() {
+ if (m_iCurrentNodeCount == 0) {
+ return;
+ }
+
+ SNode<TNodeType>* pTemp = m_pFirst;
+ if (m_iCurrentNodeCount > 0) {
+ m_iCurrentNodeCount --;
+ }
+
+ if (0 == m_iCurrentNodeCount) {
+ ResetStorage();
+ } else {
+ m_pFirst = m_pFirst->pNextNode;
+ m_pFirst->pPrevNode = NULL;
+
+ CleanOneNode (pTemp);
+ }
+ }
+
+ bool erase (TNodeType* pNode) {
+ if (0 == m_iCurrentNodeCount) {
+ return false;
+ }
+
+ SNode<TNodeType>* pTemp = m_pFirst;
+ do {
+ if (pNode == pTemp->pPointer) {
+ if (pTemp->pPrevNode) {
+ pTemp->pPrevNode->pNextNode = pTemp->pNextNode;
+ } else {
+ m_pFirst = pTemp->pNextNode;
+ }
+
+ if (pTemp->pNextNode) {
+ pTemp->pNextNode->pPrevNode = pTemp->pPrevNode;
+ }
+
+ CleanOneNode (pTemp);
+ m_iCurrentNodeCount --;
+ return true;
+ }
+
+ if (pTemp->pNextNode) {
+ pTemp = pTemp->pNextNode;
+ } else {
+ break;
+ }
+ } while (pTemp->pPointer && pTemp->pNextNode);
+ return false;
+ }
+
+ private:
+ bool ExpandList() {
+ SNode<TNodeType>* tmpCurrentList = static_cast<SNode<TNodeType>*> (malloc (m_iMaxNodeCount * 2 * sizeof (
+ SNode<TNodeType>)));
+ if (tmpCurrentList == NULL) {
+ return false;
+ }
+ InitStorage (tmpCurrentList, (m_iMaxNodeCount * 2) - 1);
+
+ SNode<TNodeType>* pTemp = m_pFirst;
+ for (int i = 0; ((i < m_iMaxNodeCount) && pTemp); i++) {
+ tmpCurrentList[i].pPointer = pTemp->pPointer;
+ pTemp = pTemp->pNextNode;
+ }
+
+ free (m_pCurrentList);
+ m_pCurrentList = tmpCurrentList;
+ m_iCurrentNodeCount = m_iMaxNodeCount;
+ m_iMaxNodeCount = m_iMaxNodeCount * 2;
+ m_pFirst = m_pCurrentList;
+ m_pCurrent = & (m_pCurrentList[m_iCurrentNodeCount - 1]);
+ return true;
+ }
+
+ void InitStorage (SNode<TNodeType>* pList, const int32_t iMaxIndex) {
+ pList[0].pPrevNode = NULL;
+ pList[0].pPointer = NULL;
+ pList[0].pNextNode = & (pList[1]);
+ for (int i = 1; i < iMaxIndex; i++) {
+ pList[i].pPrevNode = & (pList[i - 1]);
+ pList[i].pPointer = NULL;
+ pList[i].pNextNode = & (pList[i + 1]);
+ }
+ pList[iMaxIndex].pPrevNode = & (pList[iMaxIndex - 1]);
+ pList[iMaxIndex].pPointer = NULL;
+ pList[iMaxIndex].pNextNode = NULL;
+ }
+
+ SNode<TNodeType>* FindNextStorage() {
+
+ if (NULL != m_pCurrent->pNextNode) {
+ if (NULL == m_pCurrent->pNextNode->pPointer) {
+ return (m_pCurrent->pNextNode);
+ }
+ }
+
+ for (int32_t i = 0; i < m_iMaxNodeCount; i++) {
+ if (NULL == m_pCurrentList[i].pPointer) {
+ return (&m_pCurrentList[i]);
+ }
+ }
+ return NULL;
+ }
+
+ void CleanOneNode (SNode<TNodeType>* pSNode) {
+ pSNode->pPointer = NULL;
+ pSNode->pPrevNode = NULL;
+ pSNode->pNextNode = NULL;
+ }
+
+ void ResetStorage() {
+ m_pFirst = NULL;
+ m_pCurrent = m_pCurrentList;
+ InitStorage (m_pCurrentList, m_iMaxNodeCount - 1);
+ }
+
+ int32_t m_iCurrentNodeCount;
+ int32_t m_iMaxNodeCount;
+ SNode<TNodeType>* m_pCurrentList;
+ SNode<TNodeType>* m_pFirst;
+ SNode<TNodeType>* m_pCurrent;
+};
+
+}
+
+
+#endif
+
+
+
--- a/codec/common/inc/WelsThreadPool.h
+++ b/codec/common/inc/WelsThreadPool.h
@@ -47,6 +47,7 @@
#include "WelsTask.h"
#include "WelsTaskThread.h"
#include "WelsCircleQueue.h"
+#include "WelsList.h"
namespace WelsCommon {
@@ -84,8 +85,8 @@
WELS_THREAD_ERROR_CODE CreateIdleThread();
void DestroyThread (CWelsTaskThread* pThread);
WELS_THREAD_ERROR_CODE AddThreadToIdleQueue (CWelsTaskThread* pThread);
- WELS_THREAD_ERROR_CODE AddThreadToBusyMap (CWelsTaskThread* pThread);
- WELS_THREAD_ERROR_CODE RemoveThreadFromBusyMap (CWelsTaskThread* pThread);
+ WELS_THREAD_ERROR_CODE AddThreadToBusyList (CWelsTaskThread* pThread);
+ WELS_THREAD_ERROR_CODE RemoveThreadFromBusyList (CWelsTaskThread* pThread);
void AddTaskToWaitedList (IWelsTask* pTask);
CWelsTaskThread* GetIdleThread();
IWelsTask* GetWaitedTask();
@@ -99,7 +100,7 @@
//std::list<IWelsTask*> m_cWaitedTasks;
CWelsCircleQueue<IWelsTask>* m_cWaitedTasks;
CWelsCircleQueue<CWelsTaskThread>* m_cIdleThreads;
- std::map<uintptr_t, CWelsTaskThread*> m_cBusyThreads;
+ CWelsList<CWelsTaskThread>* m_cBusyThreads;
IWelsThreadPoolSink* m_pSink;
CWelsLock m_cLockPool;
--- a/codec/common/src/WelsThreadPool.cpp
+++ b/codec/common/src/WelsThreadPool.cpp
@@ -52,6 +52,7 @@
m_pSink (pSink) {
m_cWaitedTasks = new CWelsCircleQueue<IWelsTask>();
m_cIdleThreads = new CWelsCircleQueue<CWelsTaskThread>();
+ m_cBusyThreads = new CWelsList<CWelsTaskThread>();
m_iMaxThreadNum = 0;
Init (iMaxThreadNum);
@@ -63,16 +64,17 @@
delete m_cWaitedTasks;
delete m_cIdleThreads;
+ delete m_cBusyThreads;
}
WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStart (CWelsTaskThread* pThread, IWelsTask* pTask) {
- AddThreadToBusyMap (pThread);
+ AddThreadToBusyList (pThread);
return WELS_THREAD_ERROR_OK;
}
WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStop (CWelsTaskThread* pThread, IWelsTask* pTask) {
- RemoveThreadFromBusyMap (pThread);
+ RemoveThreadFromBusyList (pThread);
AddThreadToIdleQueue (pThread);
if (m_pSink) {
@@ -198,36 +200,19 @@
return WELS_THREAD_ERROR_OK;
}
-WELS_THREAD_ERROR_CODE CWelsThreadPool::AddThreadToBusyMap (CWelsTaskThread* pThread) {
+WELS_THREAD_ERROR_CODE CWelsThreadPool::AddThreadToBusyList (CWelsTaskThread* pThread) {
CWelsAutoLock cLock (m_cLockBusyTasks);
-
- uintptr_t id = pThread->GetID();
-
- std::map<uintptr_t, CWelsTaskThread*>::iterator iter = m_cBusyThreads.find (id);
-
- if (iter != m_cBusyThreads.end()) {
- return WELS_THREAD_ERROR_GENERAL;
- }
-
- m_cBusyThreads[id] = pThread;
-
+ m_cBusyThreads->push_back (pThread);
return WELS_THREAD_ERROR_OK;
}
-WELS_THREAD_ERROR_CODE CWelsThreadPool::RemoveThreadFromBusyMap (CWelsTaskThread* pThread) {
+WELS_THREAD_ERROR_CODE CWelsThreadPool::RemoveThreadFromBusyList (CWelsTaskThread* pThread) {
CWelsAutoLock cLock (m_cLockBusyTasks);
-
- uintptr_t id = pThread->GetID();
-
- std::map<uintptr_t, CWelsTaskThread*>::iterator iter = m_cBusyThreads.find (id);
-
- if (iter != m_cBusyThreads.end()) {
- m_cBusyThreads.erase (iter);
+ if (m_cBusyThreads->erase(pThread)) {
+ return WELS_THREAD_ERROR_OK;
} else {
- return WELS_THREAD_ERROR_GENERAL;
+ return WELS_THREAD_ERROR_GENERAL;
}
-
- return WELS_THREAD_ERROR_OK;
}
void CWelsThreadPool::AddTaskToWaitedList (IWelsTask* pTask) {
@@ -250,7 +235,7 @@
}
int32_t CWelsThreadPool::GetBusyThreadNum() {
- return static_cast<int32_t> (m_cBusyThreads.size());
+ return static_cast<int32_t> (m_cBusyThreads->size());
}
int32_t CWelsThreadPool::GetIdleThreadNum() {
--- /dev/null
+++ b/test/common/CWelsListTest.cpp
@@ -1,0 +1,222 @@
+#include <gtest/gtest.h>
+#include "WelsList.h"
+
+using namespace WelsCommon;
+
+TEST (CWelsList, CWelsListOne) {
+ CWelsList<int> cTestList;
+ int a = 0;
+
+ for (int i = 0; i < 60; i++) {
+ cTestList.push_back (&a);
+ EXPECT_TRUE (1 == cTestList.size()) << "after push size=" << cTestList.size() ;
+
+ cTestList.pop_front();
+ EXPECT_TRUE (0 == cTestList.size()) << "after pop size=" << cTestList.size() ;
+ }
+}
+
+TEST (CWelsList, CWelsListTen) {
+ CWelsList<int> cTestList;
+ int a = 0;
+ int* pPointer = &a;
+
+ for (int j = 0; j < 10; j++) {
+
+ for (int i = 0; i < 10; i++) {
+ EXPECT_TRUE (i == cTestList.size()) << "before push size=" << cTestList.size() ;
+ cTestList.push_back (pPointer);
+ }
+ EXPECT_TRUE (10 == cTestList.size()) << "after push size=" << cTestList.size() ;
+
+
+ for (int i = 9; i >= 0; i--) {
+ cTestList.pop_front();
+ EXPECT_TRUE (i == cTestList.size()) << "after pop size=" << cTestList.size() ;
+ }
+ }
+}
+
+TEST (CWelsList, CWelsListExpand) {
+ CWelsList<int> cTestList;
+ int a = 0;
+ int* pPointer = &a;
+
+ const int kiIncreaseNum = (rand() % 100) + 1;
+ const int kiDecreaseNum = rand() % kiIncreaseNum;
+
+ for (int j = 0; j < 10; j++) {
+
+ for (int i = 0; i < kiIncreaseNum; i++) {
+ EXPECT_TRUE (cTestList.push_back (pPointer));
+ }
+ EXPECT_TRUE (kiIncreaseNum + j * (kiIncreaseNum - kiDecreaseNum) == cTestList.size()) << "after push size=" <<
+ cTestList.size() ;
+
+ for (int i = kiDecreaseNum; i > 0; i--) {
+ cTestList.pop_front();
+ }
+ EXPECT_TRUE ((j + 1) * (kiIncreaseNum - kiDecreaseNum) == cTestList.size()) << "after pop size=" << cTestList.size() ;
+ }
+}
+
+TEST (CWelsList, CWelsListOverPop) {
+ CWelsList<int> cTestList;
+ int a = 0;
+ int* pPointer = &a;
+
+ const int kiDecreaseNum = 30000;//(rand() % 65535) + 1;
+ const int kiIncreaseNum = rand() % kiDecreaseNum;
+
+ EXPECT_TRUE (0 == cTestList.size());
+ cTestList.pop_front();
+ EXPECT_TRUE (0 == cTestList.size());
+
+ for (int i = 0; i < kiIncreaseNum; i++) {
+ EXPECT_TRUE (cTestList.push_back (pPointer));
+ }
+
+ for (int i = kiDecreaseNum; i > 0; i--) {
+ cTestList.pop_front();
+ }
+
+ EXPECT_TRUE (0 == cTestList.size());
+}
+
+
+void EraseOneInList (CWelsList<int>& cTestList, int* pPointer) {
+ int iPrevSize = cTestList.size();
+ EXPECT_TRUE (cTestList.erase (pPointer));
+ EXPECT_TRUE (cTestList.size() == (iPrevSize - 1));
+}
+
+TEST (CWelsList, CWelsListEraseOne) {
+#define TEST_LEN (4)
+ CWelsList<int> cTestList;
+ int a[TEST_LEN];
+ int* pPointer;
+
+ for (int i = 0; i < TEST_LEN; i++) {
+ a[i] = i;
+ cTestList.push_back (&a[i]);
+ }
+
+ EXPECT_TRUE (cTestList.size() == TEST_LEN);
+
+ int iEraseIdx = rand() % TEST_LEN;
+ EraseOneInList (cTestList, &a[iEraseIdx]);
+ EXPECT_TRUE (cTestList.size() == (TEST_LEN - 1));
+
+ for (int i = 0; i < TEST_LEN; i++) {
+ pPointer = cTestList.begin();
+ cTestList.pop_front();
+ if (!pPointer) {
+ EXPECT_TRUE (cTestList.size() == 0);
+ break;
+ }
+ if (i < iEraseIdx) {
+ EXPECT_TRUE (a[i] == (*pPointer));
+ } else {
+ EXPECT_TRUE (a[i + 1] == (*pPointer));
+ }
+ }
+
+ EXPECT_TRUE (0 == cTestList.size());
+}
+
+TEST (CWelsList, CWelsListEraseAll) {
+#define TEST_LEN (4)
+ CWelsList<int> cTestList;
+ int data[TEST_LEN];
+ int eraseidx[TEST_LEN] = {0};
+ int* pPointer;
+
+ for (int i = 0; i < TEST_LEN; i++) {
+ data[i] = i;
+ cTestList.push_back (&data[i]);
+ }
+ EXPECT_TRUE (cTestList.size() == TEST_LEN);
+
+ int iCurrentLen = TEST_LEN;
+ do {
+ int iEraseIdx = rand() % TEST_LEN;
+ if (0 == eraseidx[iEraseIdx]) {
+ eraseidx[iEraseIdx] = 1;
+ EraseOneInList (cTestList, &data[iEraseIdx]);
+ EXPECT_TRUE (cTestList.size() == (--iCurrentLen));
+ }
+ EXPECT_FALSE (cTestList.erase (&data[iEraseIdx]));
+
+ if (cTestList.size() == 0) {
+ break;
+ }
+
+ pPointer = cTestList.begin();
+ for (int i = 0; i < TEST_LEN; i++) {
+ if ((*pPointer) == data[i]) {
+ EXPECT_TRUE (eraseidx[i] == 0);
+ break;
+ }
+ }
+ } while (cTestList.size());
+ EXPECT_TRUE (0 == cTestList.size());
+}
+
+TEST (CWelsList, CWelsListEraseAndExpand) {
+#define TEST_LEN_10 (10)
+ CWelsList<int> cTestList;
+ int data[TEST_LEN_10];
+ int eraseidx[TEST_LEN_10] = {0};
+ int* pPointer;
+
+ for (int i = 0; i < TEST_LEN_10; i++) {
+ data[i] = i;
+ cTestList.push_back (&data[i]);
+ }
+ EXPECT_TRUE (cTestList.size() == TEST_LEN_10);
+
+ //erase some
+ int iCurrentLen = TEST_LEN_10;
+ do {
+ int iEraseIdx = rand() % TEST_LEN_10;
+ if (0 == eraseidx[iEraseIdx]) {
+ eraseidx[iEraseIdx] = 1;
+ EraseOneInList (cTestList, &data[iEraseIdx]);
+ EXPECT_TRUE (cTestList.size() == (--iCurrentLen));
+ }
+ EXPECT_FALSE (cTestList.erase (&data[iEraseIdx]));
+
+ if (cTestList.size() == 0) {
+ break;
+ }
+
+ pPointer = cTestList.begin();
+ for (int i = 0; i < TEST_LEN_10; i++) {
+ if ((*pPointer) == data[i]) {
+ EXPECT_TRUE (eraseidx[i] == 0);
+ break;
+ }
+ }
+ } while (iCurrentLen > (TEST_LEN_10 / 2));
+ EXPECT_TRUE (iCurrentLen == cTestList.size());
+
+ //expand
+ int iAddLen = rand() % 65535;
+ for (int i = 0; i < iAddLen; i++) {
+ EXPECT_TRUE (cTestList.push_back (&data[0]));
+ }
+ EXPECT_TRUE ((iCurrentLen + iAddLen) == cTestList.size());
+ EraseOneInList (cTestList, &data[0]);
+ EXPECT_TRUE ((iCurrentLen + iAddLen - 1) == cTestList.size()) << (iCurrentLen + iAddLen - 1) << "_" <<
+ cTestList.size();
+
+ //clear up
+ do {
+ pPointer = cTestList.begin();
+ EXPECT_TRUE (NULL != pPointer);
+ cTestList.pop_front();
+ } while (cTestList.size());
+
+ EXPECT_TRUE (0 == cTestList.size());
+}
+
--- a/test/common/targets.mk
+++ b/test/common/targets.mk
@@ -2,6 +2,7 @@
COMMON_UNITTEST_CPP_SRCS=\
$(COMMON_UNITTEST_SRCDIR)/ExpandPicture.cpp\
$(COMMON_UNITTEST_SRCDIR)/CWelsCircleQueue.cpp\
+ $(COMMON_UNITTEST_SRCDIR)/CWelsListTest.cpp\
COMMON_UNITTEST_OBJS += $(COMMON_UNITTEST_CPP_SRCS:.cpp=.$(OBJ))