shithub: openh264

Download patch

ref: bc566f0923d099531a573220ae7e83056f52da52
parent: eb00d5cb9ed39ffc9501cca82fbcea7218bf01d3
author: Sijia Chen <sijchen@cisco.com>
date: Thu Oct 15 06:24:48 EDT 2015

put m_cIdleThreads to CWelsCircleQueue rather than std::map
https://rbcommons.com/s/OpenH264/r/1313/

--- a/codec/common/inc/WelsCircleQueue.h
+++ b/codec/common/inc/WelsCircleQueue.h
@@ -66,19 +66,35 @@
   }
 
   int32_t push_back (TNodeType* pNode) {
-    m_pCurrentQueue[m_iCurrentListEnd] = pNode;
-    m_iCurrentListEnd ++;
-
-    if (m_iCurrentListEnd == m_iMaxNodeCount) {
-      m_iCurrentListEnd = 0;
+    if ((NULL != pNode) && (find (pNode))) {      //not checking NULL for easier testing
+      return 1;
     }
-    if (m_iCurrentListEnd == m_iCurrentListStart) {
-      int32_t ret = ExpandList();
-      if (ret) {
-        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 0;
+    return false;
   }
 
   void pop_front() {
@@ -91,9 +107,28 @@
   }
 
   TNodeType* begin() {
-    return m_pCurrentQueue[m_iCurrentListStart];
+    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 = ExpandList();
+      if (ret) {
+        return 1;
+      }
+    }
+    return 0;
+  }
+
   int32_t ExpandList() {
     TNodeType** tmpCurrentTaskQueue = static_cast<TNodeType**> (malloc (m_iMaxNodeCount * 2 * sizeof (TNodeType*)));
     if (tmpCurrentTaskQueue == NULL) {
--- a/codec/common/inc/WelsThreadPool.h
+++ b/codec/common/inc/WelsThreadPool.h
@@ -83,7 +83,7 @@
 
   WELS_THREAD_ERROR_CODE CreateIdleThread();
   void           DestroyThread (CWelsTaskThread* pThread);
-  WELS_THREAD_ERROR_CODE AddThreadToIdleMap (CWelsTaskThread* pThread);
+  WELS_THREAD_ERROR_CODE AddThreadToIdleQueue (CWelsTaskThread* pThread);
   WELS_THREAD_ERROR_CODE AddThreadToBusyMap (CWelsTaskThread* pThread);
   WELS_THREAD_ERROR_CODE RemoveThreadFromBusyMap (CWelsTaskThread* pThread);
   void           AddTaskToWaitedList (IWelsTask* pTask);
@@ -98,7 +98,7 @@
   int32_t   m_iMaxThreadNum;
   //std::list<IWelsTask*>    m_cWaitedTasks;
   CWelsCircleQueue<IWelsTask>* m_cWaitedTasks;
-  std::map<uintptr_t, CWelsTaskThread*>  m_cIdleThreads;
+  CWelsCircleQueue<CWelsTaskThread>* m_cIdleThreads;
   std::map<uintptr_t, CWelsTaskThread*>  m_cBusyThreads;
   IWelsThreadPoolSink*   m_pSink;
 
--- a/codec/common/src/WelsThreadLib.cpp
+++ b/codec/common/src/WelsThreadLib.cpp
@@ -174,6 +174,9 @@
   return WELS_THREAD_ERROR_OK;
 }
 
+void WelsSleep (uint32_t dwMilliSecond) {
+  ::Sleep (dwMilliSecond);
+}
 
 WELS_THREAD_ERROR_CODE    WelsThreadCreate (WELS_THREAD_HANDLE* thread,  LPWELS_THREAD_ROUTINE  routine,
     void* arg, WELS_THREAD_ATTR attr) {
@@ -332,11 +335,7 @@
 }
 
 void WelsSleep (uint32_t dwMilliSecond) {
-#ifdef  WIN32
-  ::Sleep (dwMilliSecond);
-#else
   usleep (dwMilliSecond * 1000);
-#endif
 }
 
 WELS_THREAD_ERROR_CODE    WelsEventWaitWithTimeOut (WELS_EVENT* event, uint32_t dwMilliseconds) {
--- a/codec/common/src/WelsThreadPool.cpp
+++ b/codec/common/src/WelsThreadPool.cpp
@@ -51,6 +51,7 @@
 CWelsThreadPool::CWelsThreadPool (IWelsThreadPoolSink* pSink, int32_t iMaxThreadNum) :
   m_pSink (pSink) {
   m_cWaitedTasks = new CWelsCircleQueue<IWelsTask>();
+  m_cIdleThreads = new CWelsCircleQueue<CWelsTaskThread>();
   m_iMaxThreadNum = 0;
 
   Init (iMaxThreadNum);
@@ -61,6 +62,7 @@
   Uninit();
 
   delete m_cWaitedTasks;
+  delete m_cIdleThreads;
 }
 
 WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStart (CWelsTaskThread* pThread, IWelsTask* pTask) {
@@ -71,7 +73,7 @@
 
 WELS_THREAD_ERROR_CODE CWelsThreadPool::OnTaskStop (CWelsTaskThread* pThread, IWelsTask* pTask) {
   RemoveThreadFromBusyMap (pThread);
-  AddThreadToIdleMap (pThread);
+  AddThreadToIdleQueue (pThread);
 
   if (m_pSink) {
     m_pSink->OnTaskExecuted (pTask);
@@ -121,10 +123,9 @@
   }
 
   m_cLockIdleTasks.Lock();
-  std::map<uintptr_t, CWelsTaskThread*>::iterator iter = m_cIdleThreads.begin();
-  while (iter != m_cIdleThreads.end()) {
-    DestroyThread (iter->second);
-    ++ iter;
+  while (m_cIdleThreads->size() > 0) {
+    DestroyThread (m_cIdleThreads->begin());
+    m_cIdleThreads->pop_front();
   }
   m_cLockIdleTasks.Unlock();
 
@@ -179,7 +180,7 @@
   }
 
   pThread->Start();
-  AddThreadToIdleMap (pThread);
+  AddThreadToIdleQueue (pThread);
 
   return WELS_THREAD_ERROR_OK;
 }
@@ -191,19 +192,9 @@
   return;
 }
 
-WELS_THREAD_ERROR_CODE CWelsThreadPool::AddThreadToIdleMap (CWelsTaskThread* pThread) {
+WELS_THREAD_ERROR_CODE CWelsThreadPool::AddThreadToIdleQueue (CWelsTaskThread* pThread) {
   CWelsAutoLock cLock (m_cLockIdleTasks);
-
-  uintptr_t id = pThread->GetID();
-
-  std::map<uintptr_t, CWelsTaskThread*>::iterator  iter = m_cIdleThreads.find (id);
-
-  if (iter != m_cIdleThreads.end()) {
-    return WELS_THREAD_ERROR_GENERAL;
-  }
-
-  m_cIdleThreads[id] = pThread;
-
+  m_cIdleThreads->push_back (pThread);
   return WELS_THREAD_ERROR_OK;
 }
 
@@ -249,15 +240,12 @@
 CWelsTaskThread*   CWelsThreadPool::GetIdleThread() {
   CWelsAutoLock cLock (m_cLockIdleTasks);
 
-  if (m_cIdleThreads.size() == 0) {
+  if (m_cIdleThreads->size() == 0) {
     return NULL;
   }
 
-  std::map<uintptr_t, CWelsTaskThread*>::iterator it = m_cIdleThreads.begin();
-  CWelsTaskThread* pThread = it->second;
-
-  m_cIdleThreads.erase (it);
-
+  CWelsTaskThread* pThread = m_cIdleThreads->begin();
+  m_cIdleThreads->pop_front();
   return pThread;
 }
 
@@ -266,7 +254,7 @@
 }
 
 int32_t  CWelsThreadPool::GetIdleThreadNum() {
-  return static_cast<int32_t> (m_cIdleThreads.size());
+  return static_cast<int32_t> (m_cIdleThreads->size());
 }
 
 int32_t  CWelsThreadPool::GetWaitedTaskNum() {
@@ -275,6 +263,7 @@
 
 IWelsTask* CWelsThreadPool::GetWaitedTask() {
   CWelsAutoLock lock (m_cLockWaitedTasks);
+
   if (m_cWaitedTasks->size() == 0) {
     return NULL;
   }
@@ -288,6 +277,7 @@
 
 void  CWelsThreadPool::ClearWaitedTasks() {
   CWelsAutoLock cLock (m_cLockWaitedTasks);
+
   if (m_pSink) {
     while (0 != m_cWaitedTasks->size()) {
       m_pSink->OnTaskCancelled (m_cWaitedTasks->begin());
--- a/test/build/win32/codec_ut/codec_unittest.vcproj
+++ b/test/build/win32/codec_ut/codec_unittest.vcproj
@@ -831,6 +831,10 @@
 			Name="common"
 			>
 			<File
+				RelativePath="..\..\..\common\CWelsCircleQueue.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\..\..\common\ExpandPicture.cpp"
 				>
 				<FileConfiguration
--- a/test/common/CWelsCircleQueue.cpp
+++ b/test/common/CWelsCircleQueue.cpp
@@ -1,6 +1,6 @@
 #include <gtest/gtest.h>
 #include "WelsCircleQueue.h"
-#include "WelsTask.h"
+#include "WelsTaskThread.h"
 
 using namespace WelsCommon;
 
@@ -81,3 +81,115 @@
   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