shithub: openh264

Download patch

ref: ea52112d45feeb615b7fec52398ed1b2ed25e973
parent: 7cbc31a0bff0f8403b4ddc2a239de65822936dcc
parent: cb6ab3211d8b98ad866aa0a3c7d9517dcc497f9b
author: HaiboZhu <haibozhu@cisco.com>
date: Fri Oct 16 12:50:39 EDT 2015

Merge pull request #2158 from sijchen/thp0a

[Common] basic thread pool functions

--- a/codec/build/iOS/common/common.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/common/common.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		0DD32A861B467902009181A1 /* WelsThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A851B467902009181A1 /* WelsThread.cpp */; };
+		0DD32A881B467911009181A1 /* WelsTaskThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A871B467911009181A1 /* WelsTaskThread.cpp */; };
+		0DD32A941B468F77009181A1 /* WelsThreadPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0DD32A931B468F77009181A1 /* WelsThreadPool.cpp */; };
 		4C3406C918D96EA600DFA14A /* arm_arch_common_macro.S in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406B218D96EA600DFA14A /* arm_arch_common_macro.S */; };
 		4C3406CA18D96EA600DFA14A /* deblocking_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406B318D96EA600DFA14A /* deblocking_neon.S */; };
 		4C3406CB18D96EA600DFA14A /* expand_picture_neon.S in Sources */ = {isa = PBXBuildFile; fileRef = 4C3406B418D96EA600DFA14A /* expand_picture_neon.S */; };
@@ -46,6 +49,16 @@
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		0DB71EF31BAB273500EABC51 /* WelsCircleQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsCircleQueue.h; sourceTree = "<group>"; };
+		0DD32A851B467902009181A1 /* WelsThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WelsThread.cpp; sourceTree = "<group>"; };
+		0DD32A871B467911009181A1 /* WelsTaskThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WelsTaskThread.cpp; sourceTree = "<group>"; };
+		0DD32A8E1B467B83009181A1 /* WelsLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsLock.h; sourceTree = "<group>"; };
+		0DD32A8F1B467C73009181A1 /* WelsTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsTask.h; sourceTree = "<group>"; };
+		0DD32A901B467C73009181A1 /* WelsTaskThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelsTaskThread.h; sourceTree = "<group>"; };
+		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>"; };
@@ -134,6 +147,13 @@
 				5BD896B81A7B837700D32B7D /* memory_align.h */,
 				4C3406C118D96EA600DFA14A /* typedefs.h */,
 				5BA8F2BE19603F3500011CE4 /* wels_common_defs.h */,
+				0DB71EF31BAB273500EABC51 /* WelsCircleQueue.h */,
+				0DEA477E1BB36FE100ADD134 /* WelsList.h */,
+				0DD32A8E1B467B83009181A1 /* WelsLock.h */,
+				0DD32A8F1B467C73009181A1 /* WelsTask.h */,
+				0DD32A901B467C73009181A1 /* WelsTaskThread.h */,
+				0DD32A911B467C73009181A1 /* WelsThread.h */,
+				0DD32A921B467C73009181A1 /* WelsThreadPool.h */,
 				5B9196F91A7F8BA40075D641 /* wels_const_common.h */,
 				4C3406C218D96EA600DFA14A /* WelsThreadLib.h */,
 			);
@@ -153,6 +173,9 @@
 				4C3406C618D96EA600DFA14A /* deblocking_common.cpp */,
 				5BDD15EC1A79027600B6CA2E /* mc.cpp */,
 				5BD896B91A7B839B00D32B7D /* memory_align.cpp */,
+				0DD32A871B467911009181A1 /* WelsTaskThread.cpp */,
+				0DD32A931B468F77009181A1 /* WelsThreadPool.cpp */,
+				0DD32A851B467902009181A1 /* WelsThread.cpp */,
 				4C3406C818D96EA600DFA14A /* WelsThreadLib.cpp */,
 			);
 			path = src;
@@ -260,6 +283,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				0DD32A941B468F77009181A1 /* WelsThreadPool.cpp in Sources */,
 				F5B8D82D190757290037849A /* mc_aarch64_neon.S in Sources */,
 				4C3406C918D96EA600DFA14A /* arm_arch_common_macro.S in Sources */,
 				F556A8241906673900E156A8 /* arm_arch64_common_macro.S in Sources */,
@@ -268,8 +292,10 @@
 				4C3406CE18D96EA600DFA14A /* crt_util_safe_x.cpp in Sources */,
 				F791965919D3BE2200F60C6B /* intra_pred_common.cpp in Sources */,
 				5BD896BA1A7B839B00D32B7D /* memory_align.cpp in Sources */,
+				0DD32A881B467911009181A1 /* WelsTaskThread.cpp in Sources */,
 				4C3406CF18D96EA600DFA14A /* deblocking_common.cpp in Sources */,
 				5BA8F2C019603F5F00011CE4 /* common_tables.cpp in Sources */,
+				0DD32A861B467902009181A1 /* WelsThread.cpp in Sources */,
 				F791965419D3B89D00F60C6B /* intra_pred_common_aarch64_neon.S in Sources */,
 				4C3406D118D96EA600DFA14A /* WelsThreadLib.cpp in Sources */,
 				4C3406CC18D96EA600DFA14A /* mc_neon.S in Sources */,
--- a/codec/build/win32/enc/WelsEncCore.vcproj
+++ b/codec/build/win32/enc/WelsEncCore.vcproj
@@ -474,7 +474,19 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\..\common\src\WelsTaskThread.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\common\src\WelsThread.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\common\src\WelsThreadLib.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\common\src\WelsThreadPool.cpp"
 				>
 			</File>
 		</Filter>
--- /dev/null
+++ b/codec/common/inc/WelsCircleQueue.h
@@ -1,0 +1,167 @@
+/*!
+ * \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    WelsCircleQueue.h
+ *
+ * \brief   for the queue function needed in ThreadPool
+ *
+ * \date    9/27/2015 Created
+ *
+ *************************************************************************************
+ */
+
+
+#ifndef _WELS_CIRCLE_QUEUE_H_
+#define _WELS_CIRCLE_QUEUE_H_
+
+#include "typedefs.h"
+
+namespace WelsCommon {
+
+template<typename TNodeType>
+class CWelsCircleQueue {
+ public:
+  CWelsCircleQueue() {
+    m_iMaxNodeCount = 50;
+    m_pCurrentQueue = static_cast<TNodeType**> (malloc (m_iMaxNodeCount * sizeof (TNodeType*)));
+    //here using array to simulate list is to avoid the frequent malloc/free of Nodes which may cause fragmented memory
+    m_iCurrentListStart = m_iCurrentListEnd = 0;
+  };
+  ~CWelsCircleQueue() {
+    free (m_pCurrentQueue);
+  };
+
+  int32_t size() {
+    return ((m_iCurrentListEnd >= m_iCurrentListStart)
+            ? (m_iCurrentListEnd - m_iCurrentListStart)
+            : (m_iMaxNodeCount - m_iCurrentListStart + m_iCurrentListEnd));
+  }
+
+  int32_t push_back (TNodeType* pNode) {
+    if ((NULL != pNode) && (find (pNode))) {      //not checking NULL for easier testing
+      return 1;
+    }
+    return InternalPushBack (pNode);
+  }
+
+  bool find (TNodeType* pNode) {
+    if (size() > 0) {
+      if (m_iCurrentListEnd > m_iCurrentListStart) {
+        for (int32_t idx = m_iCurrentListStart; idx < m_iCurrentListEnd; idx++) {
+          if (pNode == m_pCurrentQueue[idx]) {
+            return true;
+          }
+        }
+      } else {
+        for (int32_t idx = m_iCurrentListStart; idx < m_iMaxNodeCount; idx++) {
+          if (pNode == m_pCurrentQueue[idx]) {
+            return true;
+          }
+        }
+        for (int32_t idx = 0; idx < m_iCurrentListEnd; idx++) {
+          if (pNode == m_pCurrentQueue[idx]) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  void pop_front() {
+    if (size() > 0) {
+      m_pCurrentQueue[m_iCurrentListStart] = NULL;
+      m_iCurrentListStart = ((m_iCurrentListStart < (m_iMaxNodeCount - 1))
+                             ? (m_iCurrentListStart + 1)
+                             : 0);
+    }
+  }
+
+  TNodeType* begin() {
+    if (size() > 0) {
+      return m_pCurrentQueue[m_iCurrentListStart];
+    }
+    return NULL;
+  }
+ private:
+  int32_t InternalPushBack (TNodeType* pNode) {
+    m_pCurrentQueue[m_iCurrentListEnd] = pNode;
+    m_iCurrentListEnd ++;
+
+    if (m_iCurrentListEnd == m_iMaxNodeCount) {
+      m_iCurrentListEnd = 0;
+    }
+    if (m_iCurrentListEnd == m_iCurrentListStart) {
+      int32_t ret = ExpandQueue();
+      if (ret) {
+        return 1;
+      }
+    }
+    return 0;
+  }
+
+  int32_t ExpandQueue() {
+    TNodeType** tmpCurrentTaskQueue = static_cast<TNodeType**> (malloc (m_iMaxNodeCount * 2 * sizeof (TNodeType*)));
+    if (tmpCurrentTaskQueue == NULL) {
+      return 1;
+    }
+
+    memcpy (tmpCurrentTaskQueue,
+            (m_pCurrentQueue + m_iCurrentListStart),
+            (m_iMaxNodeCount - m_iCurrentListStart)*sizeof (TNodeType*));
+    if (m_iCurrentListEnd > 0) {
+      memcpy (tmpCurrentTaskQueue + m_iMaxNodeCount - m_iCurrentListStart,
+              m_pCurrentQueue,
+              m_iCurrentListEnd * sizeof (TNodeType*));
+    }
+
+    free (m_pCurrentQueue);
+
+    m_pCurrentQueue = tmpCurrentTaskQueue;
+    m_iCurrentListEnd = m_iMaxNodeCount;
+    m_iCurrentListStart = 0;
+    m_iMaxNodeCount = m_iMaxNodeCount * 2;
+
+    return 0;
+  }
+  int32_t m_iCurrentListStart;
+  int32_t m_iCurrentListEnd;
+  int32_t m_iMaxNodeCount;
+  TNodeType** m_pCurrentQueue;
+};
+
+}
+
+
+#endif
+
+
+
--- /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
+
+
+
--- /dev/null
+++ b/codec/common/inc/WelsLock.h
@@ -1,0 +1,97 @@
+/*!
+ * \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    WelsLock.h
+ *
+ * \brief   class wrapping for locks
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+#ifndef _WELS_LOCK_H_
+#define _WELS_LOCK_H_
+
+#include "macros.h"
+#include "typedefs.h"
+#include "WelsThreadLib.h"
+
+namespace WelsCommon {
+
+class CWelsLock {
+  DISALLOW_COPY_AND_ASSIGN (CWelsLock);
+ public:
+  CWelsLock() {
+    WelsMutexInit (&m_cMutex);
+  }
+
+  virtual ~CWelsLock() {
+    WelsMutexDestroy (&m_cMutex);
+  }
+
+  WELS_THREAD_ERROR_CODE  Lock() {
+    return WelsMutexLock (&m_cMutex);
+  }
+
+  WELS_THREAD_ERROR_CODE Unlock() {
+    return WelsMutexUnlock (&m_cMutex);
+  }
+
+ private:
+  WELS_MUTEX   m_cMutex;
+};
+
+class CWelsAutoLock {
+  DISALLOW_COPY_AND_ASSIGN (CWelsAutoLock);
+ public:
+  CWelsAutoLock (CWelsLock& cLock) : m_cLock (cLock) {
+    m_cLock.Lock();
+  }
+
+  virtual ~CWelsAutoLock() {
+    m_cLock.Unlock();
+  }
+
+ private:
+  CWelsLock&    m_cLock;
+};
+
+}
+
+#endif
+
+
+
+
+
+
+
--- /dev/null
+++ b/codec/common/inc/WelsTask.h
@@ -1,0 +1,59 @@
+/*!
+ * \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    WelsThreadPool.h
+ *
+ * \brief   Interfaces introduced in thread pool
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+#ifndef _WELS_TASK_H_
+#define _WELS_TASK_H_
+
+#include "codec_def.h"
+
+namespace WelsCommon {
+
+class IWelsTask {
+ public:
+  virtual ~IWelsTask() { }
+
+  virtual CM_RETURN Execute() = 0;
+};
+
+}
+
+#endif
+
+
--- /dev/null
+++ b/codec/common/inc/WelsTaskThread.h
@@ -1,0 +1,83 @@
+/*!
+ * \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    WelsTaskThread.h
+ *
+ * \brief   connecting task and thread
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+
+#ifndef _WELS_TASK_THREAD_H_
+#define _WELS_TASK_THREAD_H_
+
+
+#include "WelsTask.h"
+#include "WelsThread.h"
+
+namespace WelsCommon {
+
+class CWelsTaskThread;
+
+class IWelsTaskThreadSink {
+ public:
+  virtual WELS_THREAD_ERROR_CODE OnTaskStart (CWelsTaskThread* pThread, IWelsTask* pTask) = 0;
+  virtual WELS_THREAD_ERROR_CODE OnTaskStop (CWelsTaskThread* pThread, IWelsTask* pTask) = 0;
+};
+
+class CWelsTaskThread : public CWelsThread {
+ public:
+  CWelsTaskThread (IWelsTaskThreadSink* pSink);
+  virtual ~CWelsTaskThread();
+
+  WELS_THREAD_ERROR_CODE  SetTask (IWelsTask* pTask);
+  virtual void ExecuteTask();
+
+  uintptr_t    GetID() const {
+    return m_uiID;
+  }
+
+ private:
+  CWelsLock   m_cLockTask;
+  IWelsTaskThreadSink*   m_pSink;
+  IWelsTask*    m_pTask;
+  uintptr_t    m_uiID;
+
+  DISALLOW_COPY_AND_ASSIGN (CWelsTaskThread);
+};
+
+}
+
+#endif
+
--- /dev/null
+++ b/codec/common/inc/WelsThread.h
@@ -1,0 +1,105 @@
+/*!
+ * \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    WelsThread.h
+ *
+ * \brief   Interfaces introduced in threads
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+
+#ifndef _WELS_THREAD_H_
+#define _WELS_THREAD_H_
+
+
+#include "macros.h"
+#include "WelsLock.h"
+#include "WelsThreadLib.h"
+
+namespace WelsCommon {
+
+class CWelsThread {
+ public:
+  CWelsThread();
+  virtual ~CWelsThread();
+
+  virtual void Thread();
+  virtual void ExecuteTask() = 0;
+  virtual WELS_THREAD_ERROR_CODE Start();
+  virtual void Kill();
+
+ protected:
+  static WELS_THREAD_ROUTINE_TYPE  TheThread (void* pParam);
+
+  void SetRunning (bool bRunning) {
+    CWelsAutoLock  cLock (m_cLockStatus);
+
+    m_bRunning = bRunning;
+  }
+  void SetEndFlag (bool bEndFlag) {
+    CWelsAutoLock  cLock (m_cLockStatus);
+
+    m_bEndFlag = bEndFlag;
+  }
+
+  bool GetRunning() const {
+    return m_bRunning;
+  }
+
+  bool GetEndFlag() const {
+    return m_bEndFlag;
+  }
+
+  void SignalThread() {
+    WelsEventSignal (&m_hEvent);
+  }
+
+ private:
+  WELS_THREAD_HANDLE  m_hThread;
+  WELS_EVENT          m_hEvent;
+  CWelsLock           m_cLockStatus;
+  bool                m_bRunning;
+  bool                m_bEndFlag;
+
+  DISALLOW_COPY_AND_ASSIGN (CWelsThread);
+};
+
+
+}
+
+
+
+#endif
+
+
--- a/codec/common/inc/WelsThreadLib.h
+++ b/codec/common/inc/WelsThreadLib.h
@@ -104,8 +104,9 @@
 WELS_THREAD_ERROR_CODE    WelsMutexUnlock (WELS_MUTEX* mutex);
 WELS_THREAD_ERROR_CODE    WelsMutexDestroy (WELS_MUTEX* mutex);
 
-WELS_THREAD_ERROR_CODE    WelsEventOpen (WELS_EVENT* p_event, const char* event_name);
-WELS_THREAD_ERROR_CODE    WelsEventClose (WELS_EVENT* event, const char* event_name);
+WELS_THREAD_ERROR_CODE    WelsEventOpen (WELS_EVENT* p_event, const char* event_name = NULL);
+WELS_THREAD_ERROR_CODE    WelsEventClose (WELS_EVENT* event, const char* event_name = NULL);
+
 WELS_THREAD_ERROR_CODE    WelsEventSignal (WELS_EVENT* event);
 WELS_THREAD_ERROR_CODE    WelsEventWait (WELS_EVENT* event);
 WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds);
@@ -125,6 +126,7 @@
 
 WELS_THREAD_ERROR_CODE    WelsQueryLogicalProcessInfo (WelsLogicalProcessInfo* pInfo);
 
+void WelsSleep (uint32_t dwMilliSecond);
 
 #ifdef  __cplusplus
 }
--- /dev/null
+++ b/codec/common/inc/WelsThreadPool.h
@@ -1,0 +1,118 @@
+/*!
+ * \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    WelsThreadPool.h
+ *
+ * \brief   Interfaces introduced in thread pool
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+
+#ifndef _WELS_THREAD_POOL_H_
+#define _WELS_THREAD_POOL_H_
+
+#include <stdio.h>
+#include "WelsTask.h"
+#include "WelsTaskThread.h"
+#include "WelsCircleQueue.h"
+#include "WelsList.h"
+
+namespace WelsCommon {
+
+class IWelsThreadPoolSink {
+ public:
+  virtual WELS_THREAD_ERROR_CODE OnTaskExecuted (IWelsTask* pTask) = 0;
+  virtual WELS_THREAD_ERROR_CODE OnTaskCancelled (IWelsTask* pTask) = 0;
+};
+
+class  CWelsThreadPool : public CWelsThread, public IWelsTaskThreadSink {
+ public:
+  enum {
+    DEFAULT_THREAD_NUM = 4,
+  };
+
+  CWelsThreadPool (IWelsThreadPoolSink* pSink = NULL, int32_t iMaxThreadNum = DEFAULT_THREAD_NUM);
+  virtual ~CWelsThreadPool();
+
+  //IWelsTaskThreadSink
+  virtual WELS_THREAD_ERROR_CODE OnTaskStart (CWelsTaskThread* pThread,  IWelsTask* pTask);
+  virtual WELS_THREAD_ERROR_CODE OnTaskStop (CWelsTaskThread* pThread,  IWelsTask* pTask);
+
+  //  CWelsThread
+  virtual void ExecuteTask();
+
+  WELS_THREAD_ERROR_CODE  QueueTask (IWelsTask* pTask);
+  int32_t        GetThreadNum() const {
+    return m_iMaxThreadNum;
+  }
+
+ protected:
+  WELS_THREAD_ERROR_CODE Init (int32_t iMaxThreadNum = DEFAULT_THREAD_NUM);
+  WELS_THREAD_ERROR_CODE Uninit();
+
+  WELS_THREAD_ERROR_CODE CreateIdleThread();
+  void           DestroyThread (CWelsTaskThread* pThread);
+  WELS_THREAD_ERROR_CODE AddThreadToIdleQueue (CWelsTaskThread* pThread);
+  WELS_THREAD_ERROR_CODE AddThreadToBusyList (CWelsTaskThread* pThread);
+  WELS_THREAD_ERROR_CODE RemoveThreadFromBusyList (CWelsTaskThread* pThread);
+  void           AddTaskToWaitedList (IWelsTask* pTask);
+  CWelsTaskThread*   GetIdleThread();
+  IWelsTask*         GetWaitedTask();
+  int32_t            GetIdleThreadNum();
+  int32_t            GetBusyThreadNum();
+  int32_t            GetWaitedTaskNum();
+  void               ClearWaitedTasks();
+
+ private:
+  int32_t   m_iMaxThreadNum;
+  CWelsCircleQueue<IWelsTask>* m_cWaitedTasks;
+  CWelsCircleQueue<CWelsTaskThread>* m_cIdleThreads;
+  CWelsList<CWelsTaskThread>* m_cBusyThreads;
+  IWelsThreadPoolSink*   m_pSink;
+
+  CWelsLock   m_cLockPool;
+  CWelsLock   m_cLockWaitedTasks;
+  CWelsLock   m_cLockIdleTasks;
+  CWelsLock   m_cLockBusyTasks;
+
+  DISALLOW_COPY_AND_ASSIGN (CWelsThreadPool);
+};
+
+}
+
+
+#endif
+
+
+
--- a/codec/common/inc/macros.h
+++ b/codec/common/inc/macros.h
@@ -205,6 +205,11 @@
   return iX;
 }
 
+#define DISALLOW_COPY_AND_ASSIGN(cclass) \
+private:	\
+cclass(const cclass &);	\
+cclass& operator=(const cclass &);
+
 /*
  * Description: to check variable validation and return the specified result
  *  iResult:    value to be checked
--- /dev/null
+++ b/codec/common/src/WelsTaskThread.cpp
@@ -1,0 +1,89 @@
+/*!
+ * \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    WelsTaskThread.cpp
+ *
+ * \brief   functions for TaskThread
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+
+
+#include "WelsTaskThread.h"
+
+namespace WelsCommon {
+
+CWelsTaskThread::CWelsTaskThread (IWelsTaskThreadSink* pSink) : m_pSink (pSink) {
+  m_uiID = (uintptr_t) (this);
+  m_pTask = NULL;
+}
+
+
+CWelsTaskThread::~CWelsTaskThread() {
+}
+
+void CWelsTaskThread::ExecuteTask() {
+  CWelsAutoLock cLock (m_cLockTask);
+  if (m_pSink) {
+    m_pSink->OnTaskStart (this, m_pTask);
+  }
+
+  if (m_pTask) {
+    m_pTask->Execute();
+  }
+
+  if (m_pSink) {
+    m_pSink->OnTaskStop (this, m_pTask);
+  }
+
+  m_pTask = NULL;
+}
+
+WELS_THREAD_ERROR_CODE CWelsTaskThread::SetTask (WelsCommon::IWelsTask* pTask) {
+  CWelsAutoLock cLock (m_cLockTask);
+
+  if (!GetRunning()) {
+    return WELS_THREAD_ERROR_GENERAL;
+  }
+
+  m_pTask = pTask;
+
+  SignalThread();
+
+  return WELS_THREAD_ERROR_OK;
+}
+
+
+}
+
--- /dev/null
+++ b/codec/common/src/WelsThread.cpp
@@ -1,0 +1,125 @@
+/*!
+ * \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    WelsThreadPool.cpp
+ *
+ * \brief   functions for Thread Pool
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+#include "WelsThread.h"
+
+namespace WelsCommon {
+
+CWelsThread::CWelsThread() :
+  m_hThread (0),
+  m_bRunning (false),
+  m_bEndFlag (false) {
+  WELS_THREAD_ERROR_CODE rc = WelsEventOpen (&m_hEvent);
+
+  if (WELS_THREAD_ERROR_OK != rc) {
+    m_hEvent = NULL;
+  }
+}
+
+CWelsThread::~CWelsThread() {
+  Kill();
+  WelsEventClose (&m_hEvent);
+  m_hEvent = NULL;
+}
+
+void CWelsThread::Thread() {
+  while (true) {
+    WelsEventWait (&m_hEvent);
+
+    if (GetEndFlag()) {
+      break;
+    }
+
+    ExecuteTask();
+  }
+
+  SetRunning (false);
+}
+
+WELS_THREAD_ERROR_CODE CWelsThread::Start() {
+  if (NULL == m_hEvent) {
+    return WELS_THREAD_ERROR_GENERAL;
+  }
+
+  if (GetRunning()) {
+    return WELS_THREAD_ERROR_OK;
+  }
+
+  SetEndFlag (false);
+
+  WELS_THREAD_ERROR_CODE rc = WelsThreadCreate (&m_hThread,
+                              (LPWELS_THREAD_ROUTINE)TheThread, this, 0);
+
+  if (WELS_THREAD_ERROR_OK != rc) {
+    return rc;
+  }
+
+  while (!GetRunning()) {
+    WelsSleep (1);
+  }
+
+  return WELS_THREAD_ERROR_OK;
+}
+
+void CWelsThread::Kill() {
+  if (!GetRunning()) {
+    return;
+  }
+
+  SetEndFlag (true);
+
+  WelsEventSignal (&m_hEvent);
+  WelsThreadJoin (m_hThread);
+  return;
+}
+
+WELS_THREAD_ROUTINE_TYPE  CWelsThread::TheThread (void* pParam) {
+  CWelsThread* pThis = static_cast<CWelsThread*> (pParam);
+
+  pThis->SetRunning (true);
+
+  pThis->Thread();
+
+  WELS_THREAD_ROUTINE_RETURN (NULL);
+}
+
+}
+
+
--- a/codec/common/src/WelsThreadLib.cpp
+++ b/codec/common/src/WelsThreadLib.cpp
@@ -71,6 +71,7 @@
 
 #ifdef WINAPI_FAMILY
 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#define WP80
 using namespace Platform;
 using namespace Windows::Foundation;
 using namespace Windows::System::Threading;
@@ -174,7 +175,31 @@
   return WELS_THREAD_ERROR_OK;
 }
 
+#ifndef WP80
+void WelsSleep (uint32_t dwMilliSecond) {
+  ::Sleep (dwMilliSecond);
+}
+#else
+void WelsSleep (uint32_t dwMilliSecond) {
+  static WELS_EVENT hSleepEvent = NULL;
+  if (!hSleepEvent) {
+    WELS_EVENT hLocalSleepEvent = NULL;
+    WELS_THREAD_ERROR_CODE ret = WelsEventOpen (&hLocalSleepEvent);
+    if (WELS_THREAD_ERROR_OK != ret) {
+      return;
+    }
+    WELS_EVENT hPreviousEvent = InterlockedCompareExchangePointerRelease (&hSleepEvent, hLocalSleepEvent, NULL);
+    if (hPreviousEvent) {
+      WelsEventClose (&hLocalSleepEvent);
+    }
+    //On this singleton usage idea of using InterlockedCompareExchangePointerRelease:
+    //   similar idea of can be found at msdn blog when introducing InterlockedCompareExchangePointerRelease
+  }
 
+  WaitForSingleObject (hSleepEvent, dwMilliSecond);
+}
+#endif
+
 WELS_THREAD_ERROR_CODE    WelsThreadCreate (WELS_THREAD_HANDLE* thread,  LPWELS_THREAD_ROUTINE  routine,
     void* arg, WELS_THREAD_ATTR attr) {
 #ifdef USE_THREADPOOL
@@ -226,7 +251,7 @@
   return WELS_THREAD_ERROR_OK;
 }
 
-#else
+#else //platform: #ifdef _WIN32
 
 WELS_THREAD_ERROR_CODE    WelsThreadCreate (WELS_THREAD_HANDLE* thread,  LPWELS_THREAD_ROUTINE  routine,
     void* arg, WELS_THREAD_ATTR attr) {
@@ -274,8 +299,14 @@
 
 WELS_THREAD_ERROR_CODE    WelsEventOpen (WELS_EVENT* p_event, const char* event_name) {
 #ifdef __APPLE__
-  if (p_event == NULL || event_name == NULL)
+  if (p_event == NULL) {
     return WELS_THREAD_ERROR_GENERAL;
+  }
+  char    strSuffix[16] = { 0 };
+  if (NULL == event_name) {
+    sprintf (strSuffix, "WelsSem%ld_p%ld", (intptr_t)p_event, (long) (getpid()));
+    event_name = &strSuffix[0];
+  }
   *p_event = sem_open (event_name, O_CREAT, (S_IRUSR | S_IWUSR)/*0600*/, 0);
   if (*p_event == (sem_t*)SEM_FAILED) {
     sem_unlink (event_name);
@@ -321,8 +352,12 @@
   return err;
 }
 
-WELS_THREAD_ERROR_CODE   WelsEventWait (WELS_EVENT* event) {
+WELS_THREAD_ERROR_CODE WelsEventWait (WELS_EVENT* event) {
   return sem_wait (*event); // blocking until signaled
+}
+
+void WelsSleep (uint32_t dwMilliSecond) {
+  usleep (dwMilliSecond * 1000);
 }
 
 WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
--- /dev/null
+++ b/codec/common/src/WelsThreadPool.cpp
@@ -1,0 +1,276 @@
+/*!
+ * \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    WelsThreadPool.cpp
+ *
+ * \brief   functions for Thread Pool
+ *
+ * \date    5/09/2012 Created
+ *
+ *************************************************************************************
+ */
+
+
+#include <list>
+#include <map>
+
+#include "typedefs.h"
+#include "WelsThreadPool.h"
+
+namespace WelsCommon {
+
+
+CWelsThreadPool::CWelsThreadPool (IWelsThreadPoolSink* pSink, int32_t iMaxThreadNum) :
+  m_pSink (pSink) {
+  m_cWaitedTasks = new CWelsCircleQueue<IWelsTask>();
+  m_cIdleThreads = new CWelsCircleQueue<CWelsTaskThread>();
+  m_cBusyThreads = new CWelsList<CWelsTaskThread>();
+  m_iMaxThreadNum = 0;
+
+  Init (iMaxThreadNum);
+}
+
+
+CWelsThreadPool::~CWelsThreadPool() {
+  Uninit();
+
+  delete m_cWaitedTasks;
+  delete m_cIdleThreads;
+  delete m_cBusyThreads;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStart (CWelsTaskThread* pThread, IWelsTask* pTask) {
+  AddThreadToBusyList (pThread);
+
+  return WELS_THREAD_ERROR_OK;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStop (CWelsTaskThread* pThread, IWelsTask* pTask) {
+  RemoveThreadFromBusyList (pThread);
+  AddThreadToIdleQueue (pThread);
+
+  if (m_pSink) {
+    m_pSink->OnTaskExecuted (pTask);
+  }
+
+  //WELS_INFO_TRACE("ThreadPool: Task "<<(uint32_t)pTask<<" Finished, Thread "<<(uint32_t)pThread<<" put to idle list");
+
+  SignalThread();
+  return WELS_THREAD_ERROR_OK;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::Init (int32_t iMaxThreadNum) {
+  CWelsAutoLock  cLock (m_cLockPool);
+  //WELS_INFO_TRACE("Enter WelsThreadPool Init");
+
+  int32_t i;
+
+  if (iMaxThreadNum <= 0)  iMaxThreadNum = 1;
+  m_iMaxThreadNum = iMaxThreadNum;
+
+  for (i = 0; i < m_iMaxThreadNum; i++) {
+    if (WELS_THREAD_ERROR_OK != CreateIdleThread()) {
+      return WELS_THREAD_ERROR_GENERAL;
+    }
+  }
+
+  if (WELS_THREAD_ERROR_OK != Start()) {
+    return WELS_THREAD_ERROR_GENERAL;
+  }
+
+  return WELS_THREAD_ERROR_OK;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::Uninit() {
+  WELS_THREAD_ERROR_CODE iReturn = WELS_THREAD_ERROR_OK;
+  CWelsAutoLock  cLock (m_cLockPool);
+
+  ClearWaitedTasks();
+
+  while (GetBusyThreadNum() > 0) {
+    //WELS_INFO_TRACE ("CWelsThreadPool::Uninit - Waiting all thread to exit");
+    WelsSleep (10);
+  }
+
+  if (GetIdleThreadNum() != m_iMaxThreadNum) {
+    iReturn = WELS_THREAD_ERROR_GENERAL;
+  }
+
+  m_cLockIdleTasks.Lock();
+  while (m_cIdleThreads->size() > 0) {
+    DestroyThread (m_cIdleThreads->begin());
+    m_cIdleThreads->pop_front();
+  }
+  m_cLockIdleTasks.Unlock();
+
+  m_iMaxThreadNum = 0;
+  Kill();
+
+  return iReturn;
+}
+
+void CWelsThreadPool::ExecuteTask() {
+  //WELS_INFO_TRACE("ThreadPool: schedule tasks");
+  CWelsTaskThread* pThread = NULL;
+  IWelsTask*    pTask = NULL;
+  while (GetWaitedTaskNum() > 0) {
+    pThread = GetIdleThread();
+    if (pThread == NULL) {
+      break;
+    }
+    pTask = GetWaitedTask();
+    //WELS_INFO_TRACE("ThreadPool:  ExecuteTask = "<<(uint32_t)(pTask)<<" at thread = "<<(uint32_t)(pThread));
+    pThread->SetTask (pTask);
+  }
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::QueueTask (IWelsTask* pTask) {
+  CWelsAutoLock  cLock (m_cLockPool);
+
+  //WELS_INFO_TRACE("ThreadPool:  QueueTask = "<<(uint32_t)(pTask));
+  if (GetWaitedTaskNum() == 0) {
+    CWelsTaskThread* pThread = GetIdleThread();
+
+    if (pThread != NULL) {
+      //WELS_INFO_TRACE("ThreadPool:  ExecuteTask = "<<(uint32_t)(pTask));
+      pThread->SetTask (pTask);
+
+      return WELS_THREAD_ERROR_OK;
+    }
+  }
+
+  AddTaskToWaitedList (pTask);
+
+  SignalThread();
+
+  return WELS_THREAD_ERROR_OK;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::CreateIdleThread() {
+  CWelsTaskThread* pThread = new CWelsTaskThread (this);
+
+  if (NULL == pThread) {
+    return WELS_THREAD_ERROR_GENERAL;
+  }
+
+  pThread->Start();
+  AddThreadToIdleQueue (pThread);
+
+  return WELS_THREAD_ERROR_OK;
+}
+
+void  CWelsThreadPool::DestroyThread (CWelsTaskThread* pThread) {
+  pThread->Kill();
+  delete pThread;
+
+  return;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::AddThreadToIdleQueue (CWelsTaskThread* pThread) {
+  CWelsAutoLock cLock (m_cLockIdleTasks);
+  m_cIdleThreads->push_back (pThread);
+  return WELS_THREAD_ERROR_OK;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::AddThreadToBusyList (CWelsTaskThread* pThread) {
+  CWelsAutoLock cLock (m_cLockBusyTasks);
+  m_cBusyThreads->push_back (pThread);
+  return WELS_THREAD_ERROR_OK;
+}
+
+WELS_THREAD_ERROR_CODE CWelsThreadPool::RemoveThreadFromBusyList (CWelsTaskThread* pThread) {
+  CWelsAutoLock cLock (m_cLockBusyTasks);
+  if (m_cBusyThreads->erase(pThread)) {
+      return WELS_THREAD_ERROR_OK;
+  } else {
+        return WELS_THREAD_ERROR_GENERAL;
+  }
+}
+
+void  CWelsThreadPool::AddTaskToWaitedList (IWelsTask* pTask) {
+  CWelsAutoLock  cLock (m_cLockWaitedTasks);
+
+  m_cWaitedTasks->push_back (pTask);
+  return;
+}
+
+CWelsTaskThread*   CWelsThreadPool::GetIdleThread() {
+  CWelsAutoLock cLock (m_cLockIdleTasks);
+
+  if (m_cIdleThreads->size() == 0) {
+    return NULL;
+  }
+
+  CWelsTaskThread* pThread = m_cIdleThreads->begin();
+  m_cIdleThreads->pop_front();
+  return pThread;
+}
+
+int32_t  CWelsThreadPool::GetBusyThreadNum() {
+  return m_cBusyThreads->size();
+}
+
+int32_t  CWelsThreadPool::GetIdleThreadNum() {
+  return m_cIdleThreads->size();
+}
+
+int32_t  CWelsThreadPool::GetWaitedTaskNum() {
+  return m_cWaitedTasks->size();
+}
+
+IWelsTask* CWelsThreadPool::GetWaitedTask() {
+  CWelsAutoLock lock (m_cLockWaitedTasks);
+
+  if (m_cWaitedTasks->size() == 0) {
+    return NULL;
+  }
+
+  IWelsTask* pTask = m_cWaitedTasks->begin();
+
+  m_cWaitedTasks->pop_front();
+
+  return pTask;
+}
+
+void  CWelsThreadPool::ClearWaitedTasks() {
+  CWelsAutoLock cLock (m_cLockWaitedTasks);
+
+  if (m_pSink) {
+    while (0 != m_cWaitedTasks->size()) {
+      m_pSink->OnTaskCancelled (m_cWaitedTasks->begin());
+      m_cWaitedTasks->pop_front();
+    }
+  }
+}
+
+}
+
+
--- a/codec/common/targets.mk
+++ b/codec/common/targets.mk
@@ -12,7 +12,10 @@
 	$(COMMON_SRCDIR)/src/sad_common.cpp\
 	$(COMMON_SRCDIR)/src/utils.cpp\
 	$(COMMON_SRCDIR)/src/welsCodecTrace.cpp\
+	$(COMMON_SRCDIR)/src/WelsTaskThread.cpp\
+	$(COMMON_SRCDIR)/src/WelsThread.cpp\
 	$(COMMON_SRCDIR)/src/WelsThreadLib.cpp\
+	$(COMMON_SRCDIR)/src/WelsThreadPool.cpp\
 
 COMMON_OBJS += $(COMMON_CPP_SRCS:.cpp=.$(OBJ))
 
--- a/test/build/win32/codec_ut/codec_unittest.vcproj
+++ b/test/build/win32/codec_ut/codec_unittest.vcproj
@@ -831,6 +831,14 @@
 			Name="common"
 			>
 			<File
+				RelativePath="..\..\..\common\CWelsCircleQueue.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\..\..\common\CWelsListTest.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\common\ExpandPicture.cpp"
 				>
 				<FileConfiguration
--- /dev/null
+++ b/test/common/CWelsCircleQueue.cpp
@@ -1,0 +1,196 @@
+#include <gtest/gtest.h>
+#include "WelsCircleQueue.h"
+#include "WelsTaskThread.h"
+
+using namespace WelsCommon;
+
+TEST (CWelsCircleQueue, CWelsCircleQueueOne) {
+  CWelsCircleQueue<IWelsTask> cTaskList;
+  IWelsTask* pTask = NULL;
+
+  for (int i = 0; i < 60; i++) {
+    cTaskList.push_back (pTask);
+    EXPECT_TRUE (1 == cTaskList.size()) << "after push size=" << cTaskList.size() ;
+
+    cTaskList.pop_front();
+    EXPECT_TRUE (0 == cTaskList.size()) << "after pop size=" << cTaskList.size() ;
+  }
+}
+
+TEST (CWelsCircleQueue, CWelsCircleQueueTen) {
+  CWelsCircleQueue<IWelsTask> cTaskList;
+  IWelsTask* pTask = NULL;
+
+  for (int j = 0; j < 10; j++) {
+
+    for (int i = 0; i < 10; i++) {
+      EXPECT_TRUE (i == cTaskList.size()) << "before push size=" << cTaskList.size() ;
+      cTaskList.push_back (pTask);
+    }
+    EXPECT_TRUE (10 == cTaskList.size()) << "after push size=" << cTaskList.size() ;
+
+
+    for (int i = 9; i >= 0; i--) {
+      cTaskList.pop_front();
+      EXPECT_TRUE (i == cTaskList.size()) << "after pop size=" << cTaskList.size() ;
+    }
+  }
+}
+
+TEST (CWelsCircleQueue, CWelsCircleQueueExpand) {
+  CWelsCircleQueue<IWelsTask> cTaskList;
+  IWelsTask* pTask = NULL;
+
+  const int kiIncreaseNum = (rand() % 65535) + 1;
+  const int kiDecreaseNum = rand() % kiIncreaseNum;
+
+  for (int j = 0; j < 10; j++) {
+
+    for (int i = 0; i < kiIncreaseNum; i++) {
+      cTaskList.push_back (pTask);
+    }
+    EXPECT_TRUE (kiIncreaseNum + j * (kiIncreaseNum - kiDecreaseNum) == cTaskList.size()) << "after push size=" <<
+        cTaskList.size() ;
+
+    for (int i = kiDecreaseNum; i > 0; i--) {
+      cTaskList.pop_front();
+    }
+    EXPECT_TRUE ((j + 1) * (kiIncreaseNum - kiDecreaseNum) == cTaskList.size()) << "after pop size=" << cTaskList.size() ;
+  }
+}
+
+TEST (CWelsCircleQueue, CWelsCircleQueueOverPop) {
+  CWelsCircleQueue<IWelsTask> cTaskList;
+  IWelsTask* pTask = NULL;
+
+  const int kiDecreaseNum = (rand() % 65535) + 1;
+  const int kiIncreaseNum = rand() % kiDecreaseNum;
+
+  EXPECT_TRUE (0 == cTaskList.size());
+  cTaskList.pop_front();
+  EXPECT_TRUE (0 == cTaskList.size());
+
+  for (int i = 0; i < kiIncreaseNum; i++) {
+    cTaskList.push_back (pTask);
+  }
+
+  for (int i = kiDecreaseNum; i > 0; i--) {
+    cTaskList.pop_front();
+  }
+
+  EXPECT_TRUE (0 == cTaskList.size());
+}
+
+TEST (CWelsCircleQueue, CWelsCircleQueueOnDuplication) {
+  int32_t a, b, c;
+  CWelsCircleQueue<int32_t> cThreadQueue;
+  //CWelsCircleQueue<IWelsTask> cThreadQueue;
+  int32_t* pObject1 = &a;
+  int32_t* pObject2 = &b;
+  int32_t* pObject3 = &c;
+
+  //initial adding
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pObject1));
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pObject2));
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pObject3));
+  EXPECT_TRUE (3 == cThreadQueue.size());
+
+  //try failed adding
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pObject3));
+  EXPECT_TRUE (3 == cThreadQueue.size());
+
+  //try pop
+  EXPECT_TRUE (pObject1 == cThreadQueue.begin());
+  cThreadQueue.pop_front();
+  EXPECT_TRUE (2 == cThreadQueue.size());
+
+  //try what currently in
+  EXPECT_TRUE (cThreadQueue.find (pObject2));
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pObject2));
+  EXPECT_TRUE (cThreadQueue.find (pObject3));
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pObject3));
+  EXPECT_TRUE (2 == cThreadQueue.size());
+
+  //add back
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pObject1));
+  EXPECT_TRUE (3 == cThreadQueue.size());
+
+  //another pop
+  EXPECT_TRUE (pObject2 == cThreadQueue.begin());
+  cThreadQueue.pop_front();
+  cThreadQueue.pop_front();
+  EXPECT_TRUE (1 == cThreadQueue.size());
+
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pObject1));
+  EXPECT_TRUE (1 == cThreadQueue.size());
+
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pObject3));
+  EXPECT_TRUE (2 == cThreadQueue.size());
+
+  //clean-up
+  while (NULL != cThreadQueue.begin()) {
+    cThreadQueue.pop_front();
+  }
+  EXPECT_TRUE (0 == cThreadQueue.size());
+}
+
+#ifndef __APPLE__
+TEST (CWelsCircleQueue, CWelsCircleQueueOnThread) {
+  CWelsCircleQueue<CWelsTaskThread> cThreadQueue;
+  CWelsTaskThread* pTaskThread1 = new CWelsTaskThread (NULL); //this initialization seemed making prob on osx?
+  EXPECT_TRUE (NULL != pTaskThread1);
+  CWelsTaskThread* pTaskThread2 = new CWelsTaskThread (NULL);
+  EXPECT_TRUE (NULL != pTaskThread2);
+  CWelsTaskThread* pTaskThread3 = new CWelsTaskThread (NULL);
+  EXPECT_TRUE (NULL != pTaskThread3);
+
+  //initial adding
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pTaskThread1));
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pTaskThread2));
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pTaskThread3));
+  EXPECT_TRUE (3 == cThreadQueue.size());
+
+  //try failed adding
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pTaskThread3));
+  EXPECT_TRUE (3 == cThreadQueue.size());
+
+  //try pop
+  EXPECT_TRUE (pTaskThread1 == cThreadQueue.begin());
+  cThreadQueue.pop_front();
+  EXPECT_TRUE (2 == cThreadQueue.size());
+
+  //try what currently in
+  EXPECT_TRUE (cThreadQueue.find (pTaskThread2));
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pTaskThread2));
+  EXPECT_TRUE (cThreadQueue.find (pTaskThread3));
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pTaskThread3));
+  EXPECT_TRUE (2 == cThreadQueue.size());
+
+  //add back
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pTaskThread1));
+  EXPECT_TRUE (3 == cThreadQueue.size());
+
+  //another pop
+  EXPECT_TRUE (pTaskThread2 == cThreadQueue.begin());
+  cThreadQueue.pop_front();
+  cThreadQueue.pop_front();
+  EXPECT_TRUE (1 == cThreadQueue.size());
+
+  EXPECT_FALSE (0 == cThreadQueue.push_back (pTaskThread1));
+  EXPECT_TRUE (1 == cThreadQueue.size());
+
+  EXPECT_TRUE (0 == cThreadQueue.push_back (pTaskThread3));
+  EXPECT_TRUE (2 == cThreadQueue.size());
+
+  //clean-up
+  while (NULL != cThreadQueue.begin()) {
+    cThreadQueue.pop_front();
+  }
+  EXPECT_TRUE (0 == cThreadQueue.size());
+
+  delete pTaskThread1;
+  delete pTaskThread2;
+  delete pTaskThread3;
+}
+#endif
+
--- /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
@@ -1,6 +1,8 @@
 COMMON_UNITTEST_SRCDIR=test/common
 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))