ref: eb00d5cb9ed39ffc9501cca82fbcea7218bf01d3
parent: 757a596e97d91a3b55644ce5eca1d8e72e218a1d
author: Sijia Chen <[email protected]>
date: Thu Oct 15 06:11:29 EDT 2015
change std::list to internal implementation and add the new ut file for CWelsCircleQueue https://rbcommons.com/s/OpenH264/r/1310/
--- a/codec/build/iOS/common/common.xcodeproj/project.pbxproj
+++ b/codec/build/iOS/common/common.xcodeproj/project.pbxproj
@@ -49,6 +49,7 @@
/* 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>"; };
@@ -145,6 +146,7 @@
5BD896B81A7B837700D32B7D /* memory_align.h */,
4C3406C118D96EA600DFA14A /* typedefs.h */,
5BA8F2BE19603F3500011CE4 /* wels_common_defs.h */,
+ 0DB71EF31BAB273500EABC51 /* WelsCircleQueue.h */,
0DD32A8E1B467B83009181A1 /* WelsLock.h */,
0DD32A8F1B467C73009181A1 /* WelsTask.h */,
0DD32A901B467C73009181A1 /* WelsTaskThread.h */,
--- /dev/null
+++ b/codec/common/inc/WelsCircleQueue.h
@@ -1,0 +1,134 @@
+/*!
+ * \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) {
+ m_pCurrentQueue[m_iCurrentListEnd] = pNode;
+ m_iCurrentListEnd ++;
+
+ if (m_iCurrentListEnd == m_iMaxNodeCount) {
+ m_iCurrentListEnd = 0;
+ }
+ if (m_iCurrentListEnd == m_iCurrentListStart) {
+ int32_t ret = ExpandList();
+ if (ret) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ void pop_front() {
+ if (size() > 0) {
+ m_pCurrentQueue[m_iCurrentListStart] = NULL;
+ m_iCurrentListStart = ((m_iCurrentListStart < (m_iMaxNodeCount - 1))
+ ? (m_iCurrentListStart + 1)
+ : 0);
+ }
+ }
+
+ TNodeType* begin() {
+ return m_pCurrentQueue[m_iCurrentListStart];
+ }
+ private:
+ int32_t ExpandList() {
+ 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
+
+
+
--- a/codec/common/inc/WelsThreadPool.h
+++ b/codec/common/inc/WelsThreadPool.h
@@ -43,9 +43,10 @@
#define _WELS_THREAD_POOL_H_
#include <map>
-
+#include <stdio.h>
#include "WelsTask.h"
#include "WelsTaskThread.h"
+#include "WelsCircleQueue.h"
namespace WelsCommon {
@@ -55,7 +56,6 @@
virtual WELS_THREAD_ERROR_CODE OnTaskCancelled (IWelsTask* pTask) = 0;
};
-
class CWelsThreadPool : public CWelsThread, public IWelsTaskThreadSink {
public:
enum {
@@ -96,7 +96,8 @@
private:
int32_t m_iMaxThreadNum;
- std::list<IWelsTask*> m_cWaitedTasks;
+ //std::list<IWelsTask*> m_cWaitedTasks;
+ CWelsCircleQueue<IWelsTask>* m_cWaitedTasks;
std::map<uintptr_t, CWelsTaskThread*> m_cIdleThreads;
std::map<uintptr_t, CWelsTaskThread*> m_cBusyThreads;
IWelsThreadPoolSink* m_pSink;
--- a/codec/common/src/WelsThreadPool.cpp
+++ b/codec/common/src/WelsThreadPool.cpp
@@ -50,6 +50,7 @@
CWelsThreadPool::CWelsThreadPool (IWelsThreadPoolSink* pSink, int32_t iMaxThreadNum) :
m_pSink (pSink) {
+ m_cWaitedTasks = new CWelsCircleQueue<IWelsTask>();
m_iMaxThreadNum = 0;
Init (iMaxThreadNum);
@@ -58,6 +59,8 @@
CWelsThreadPool::~CWelsThreadPool() {
Uninit();
+
+ delete m_cWaitedTasks;
}
WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStart (CWelsTaskThread* pThread, IWelsTask* pTask) {
@@ -239,7 +242,7 @@
void CWelsThreadPool::AddTaskToWaitedList (IWelsTask* pTask) {
CWelsAutoLock cLock (m_cLockWaitedTasks);
- m_cWaitedTasks.push_back (pTask);
+ m_cWaitedTasks->push_back (pTask);
return;
}
@@ -267,20 +270,18 @@
}
int32_t CWelsThreadPool::GetWaitedTaskNum() {
- return static_cast<int32_t> (m_cWaitedTasks.size());
+ return m_cWaitedTasks->size();
}
IWelsTask* CWelsThreadPool::GetWaitedTask() {
CWelsAutoLock lock (m_cLockWaitedTasks);
-
- if (m_cWaitedTasks.size() == 0) {
+ if (m_cWaitedTasks->size() == 0) {
return NULL;
}
- std::list<IWelsTask*>::iterator it = m_cWaitedTasks.begin();
- IWelsTask* pTask = *it;
+ IWelsTask* pTask = m_cWaitedTasks->begin();
- m_cWaitedTasks.pop_front();
+ m_cWaitedTasks->pop_front();
return pTask;
}
@@ -287,17 +288,12 @@
void CWelsThreadPool::ClearWaitedTasks() {
CWelsAutoLock cLock (m_cLockWaitedTasks);
-
- std::list<IWelsTask*>::iterator iter = m_cWaitedTasks.begin();
-
if (m_pSink) {
- while (iter != m_cWaitedTasks.end()) {
- m_pSink->OnTaskCancelled (*iter);
- ++ iter;
+ while (0 != m_cWaitedTasks->size()) {
+ m_pSink->OnTaskCancelled (m_cWaitedTasks->begin());
+ m_cWaitedTasks->pop_front();
}
}
-
- m_cWaitedTasks.clear();
}
}
--- /dev/null
+++ b/test/common/CWelsCircleQueue.cpp
@@ -1,0 +1,83 @@
+#include <gtest/gtest.h>
+#include "WelsCircleQueue.h"
+#include "WelsTask.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());
+}
+
--- a/test/common/targets.mk
+++ b/test/common/targets.mk
@@ -1,6 +1,7 @@
COMMON_UNITTEST_SRCDIR=test/common
COMMON_UNITTEST_CPP_SRCS=\
$(COMMON_UNITTEST_SRCDIR)/ExpandPicture.cpp\
+ $(COMMON_UNITTEST_SRCDIR)/CWelsCircleQueue.cpp\
COMMON_UNITTEST_OBJS += $(COMMON_UNITTEST_CPP_SRCS:.cpp=.$(OBJ))