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))