织梦CMS - 轻松建站从此开始!

罗索

WebRTC音视频引擎研究(3)--临界区设计、临界资源访问--CriticalS

落鹤生 发布于 2013-03-06 14:49 点击:次 
临界区设计、临界资源访问--CriticalSectionWrapper
TAG:

1、临界区与临界资源相关概念

临界区
        不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。每个进程中访问临界资源的那段代码称为临界区(Critical Section)。 
每个进程中访问临界资源的那段程序称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
多个进程中涉及到同一个临界资源的临界区称为相关临界区。
进程进入临界区的调度原则是: 

       ①如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。

       ②任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。

       ③进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。

       ④如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。

   临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和 LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION结构对象必须经过 InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保 护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。

2、WebRTC中临界区和临界资源

      在WebRTC源码里,对线程互斥访问临界资源设计一个良好的面向对象的实现方法。

      大体框图:

        

图示说明:

       (1)CriticalSectionWrapper类用于封装临界区的操作,包括windows平台和非windows平台的;直接使用CriticalSectionWrapper定义临界区;

       (2)CriticalSectionWrapper类是CriticalSectionWindows和CriticalSectionPosix的父类;CriticalSectionWindows表示Windows平台下使用Windows API定义临界区,同理CriticalSectionPosix表示非Windows平台下使用Posix定义临界区;

       (3)CriticalSectionScoped类的构造函数为CriticalSectionScoped(CriticalSectionWrapper& critsec),CriticalSectionWrapper的引用作为参数,(注意:CriticalSectionWrapper构造函数返回的并不是它本身,而是根据平台选择返回它的派生类对象,返回CriticalSectionWindows对象或者CriticalSectionPosix对象,以此达到CriticalSectionWrapper封装的目的)并且在定义CriticalSectionScoped的同时进入临界区;CriticalSectionScoped析构函数离开临界区;


定义CriticalSectionWrapper类和CriticalSectionScoped类:(critical_section_wrapper.h)

  1. //=========critical_section_wrapper.h 
  2. #ifndef CRITICAL_SECTION_WRAPPER_H 
  3. #define CRITICAL_SECTION_WRAPPER_H 
  4.  
  5. namespace webrtc { 
  6.     class CriticalSectionWrapper 
  7.     { 
  8.     public
  9.         // Factory method, constructor disabled 
  10.         static CriticalSectionWrapper* CreateCriticalSection();//工厂方法,创建临界区,返回指针 
  11.  
  12.         virtual ~CriticalSectionWrapper() {} 
  13.  
  14.         // Tries to grab lock, beginning of a critical section. Will wait for the 
  15.         // lock to become available if the grab failed. 
  16.         virtual void Enter() = 0; 
  17.  
  18.         // Returns a grabbed lock, end of critical section. 
  19.         virtual void Leave() = 0; 
  20.     }; 
  21.  
  22.     // RAII extension of the critical section. Prevents Enter/Leave missmatches and 
  23.     // provides more compact critical section syntax. 
  24.     class CriticalSectionScoped 
  25.     { 
  26.     public
  27.         CriticalSectionScoped(CriticalSectionWrapper& critsec) //构造函数,进入临界区 
  28.             : 
  29.         _ptrCritSec(&critsec) 
  30.         { 
  31.             _ptrCritSec->Enter(); 
  32.         } 
  33.  
  34.         ~CriticalSectionScoped() //析构函数,保证离开临界区 
  35.         { 
  36.             if (_ptrCritSec) 
  37.             { 
  38.                 Leave(); 
  39.             } 
  40.         } 
  41.  
  42.     private
  43.         void Leave() 
  44.         { 
  45.             _ptrCritSec->Leave(); 
  46.             _ptrCritSec = 0; 
  47.         } 
  48.  
  49.         CriticalSectionWrapper* _ptrCritSec; 
  50.     }; 
  51. // namespace 
  52. #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CRITICAL_SECTION_WRAPPER_H_ 

CriticalSectionWrapper类实现:(critical_section.cpp)

  1. //=========== critical_section.cpp 
  2. #if defined(_WIN32) 
  3. #include <windows.h>  
  4. #include "critical_section_windows.h" //使用Windows平台API 
  5. #else 
  6. #include "critical_section_posix.h" //使用posix 
  7. #endif 
  8.  
  9. namespace webrtc { 
  10.     CriticalSectionWrapper* CriticalSectionWrapper::CreateCriticalSection() 
  11.     { 
  12. #ifdef _WIN32 
  13.         return new CriticalSectionWindows();//Windows平台,返回CriticalSectionWindows对象 
  14. #else 
  15.         return new CriticalSectionPosix(); //非Windows平台,返回CriticalSectionPosix对象 
  16. #endif 
  17.     } 
  18. // namespace webrt 

Windows平台下临界区操作CriticalSectionWindows API 定义头文件(critical_section_windows.h)

  1. //============== critical_section_windows.h 
  2. #ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_ 
  3. #define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_ 
  4.  
  5. //#include "typedefs.h" 
  6. #include "critical_section_wrapper.h" 
  7. #include <windows.h>  //使用Windows平台API 
  8.  
  9. namespace webrtc { 
  10.     class CriticalSectionWindows : public CriticalSectionWrapper 
  11.     { 
  12.     public
  13.         CriticalSectionWindows(); 
  14.  
  15.         virtual ~CriticalSectionWindows(); 
  16.  
  17.         virtual void Enter(); 
  18.         virtual void Leave(); 
  19.  
  20.     private
  21.         CRITICAL_SECTION crit; 
  22.  
  23.         //friend class ConditionVariableWindows; 
  24.     }; 
  25. // namespace webrtc 
  26.  
  27. #endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_ 

Windows平台下临界区操作CriticalSectionWindows类 API 实现文件(critical_section_windows.cpp)

  1. //============= critical_section_windows.cpp 
  2. #include "critical_section_windows.h" 
  3.  
  4. namespace webrtc { 
  5.     CriticalSectionWindows::CriticalSectionWindows() 
  6.     { 
  7.         InitializeCriticalSection(&crit);   //构造函数初始化临界区 
  8.     } 
  9.  
  10.     CriticalSectionWindows::~CriticalSectionWindows() 
  11.     { 
  12.         DeleteCriticalSection(&crit);
  13. //析构函数删除临界区,利用类来管理资源的思想,Effective C++思想 
  14.     } 
  15.  
  16.     void 
  17.         CriticalSectionWindows::Enter() 
  18.     { 
  19.         EnterCriticalSection(&crit);        //进入临界资源 
  20.     } 
  21.  
  22.     void 
  23.         CriticalSectionWindows::Leave() 
  24.     { 
  25.         LeaveCriticalSection(&crit);        //离开临界资源 
  26.     } 
  27. // namespace webrtc 

非Windows平台下临界区操作CriticalSectionPosix API 定义头文件(critical_section_posix.h)

  1. #ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_ 
  2. #define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_ 
  3.  
  4. //非Windows平台使用Posix的临界资源 
  5.  
  6. #include "critical_section_wrapper.h" 
  7.  
  8. #include <pthread.h> //使用Posix 
  9.  
  10. namespace webrtc { 
  11. class CriticalSectionPosix : public CriticalSectionWrapper 
  12. public
  13.     CriticalSectionPosix(); 
  14.  
  15.     virtual ~CriticalSectionPosix(); 
  16.  
  17.     virtual void Enter(); 
  18.     virtual void Leave(); 
  19.  
  20. private
  21.     pthread_mutex_t _mutex; 
  22.     //friend class ConditionVariablePosix; 
  23. }; 
  24. // namespace webrtc 
  25.  
  26. #endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_POSIX_H_ 

非Windows平台下临界区操作CriticalSectionPosix类 API 实现文件(critical_section_posix.cpp)

  1. #include "critical_section_posix.h" 
  2.  
  3. namespace webrtc { 
  4. CriticalSectionPosix::CriticalSectionPosix() 
  5.     pthread_mutexattr_t attr; 
  6.     pthread_mutexattr_init(&attr); 
  7.     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 
  8.     pthread_mutex_init(&_mutex, &attr); 
  9.  
  10. CriticalSectionPosix::~CriticalSectionPosix() 
  11.     pthread_mutex_destroy(&_mutex); 
  12.  
  13. void 
  14. CriticalSectionPosix::Enter() 
  15.     pthread_mutex_lock(&_mutex); 
  16.  
  17. void 
  18. CriticalSectionPosix::Leave() 
  19.     pthread_mutex_unlock(&_mutex); 
  20. // namespace webrtc 

3、使用CriticalSectionWrapper和CriticalSectionScoped示例

设备池数据是临界资源,为保证临界资源不被破坏,必须使用临界区实现互斥访问:

头文件:...src\video_engine\main\test\WindowsTest\CaptureDevicePool.h

  1. #pragma once 
  2.  
  3. #include "common_types.h" 
  4.  
  5. #include "vie_base.h" 
  6. #include "vie_capture.h" 
  7. #include "vie_file.h" 
  8. #include "map_wrapper.h" 
  9.  
  10. namespace webrtc { 
  11. class CriticalSectionWrapper; 
  12. using namespace webrtc; 
  13. class CaptureDevicePool 
  14. public
  15.     CaptureDevicePool(VideoEngine* videoEngine); 
  16.     ~CaptureDevicePool(void); 
  17.     WebRtc_Word32 GetCaptureDevice(int& captureId, const char uniqeDeviceName[256]); 
  18.     WebRtc_Word32 ReturnCaptureDevice(int captureId); 
  19.  
  20.     private:  
  21.         struct DeviceItem 
  22.         { 
  23.             int captureId; 
  24.             WebRtc_Word32 refCount; 
  25.             char uniqeDeviceName[256]; 
  26.             DeviceItem() 
  27.             { 
  28.                 captureId=-1; 
  29.                 refCount=0; 
  30.             } 
  31.         }; 
  32.         CriticalSectionWrapper& _critSect; 
  33.         ViECapture* _vieCapture; 
  34.         ViEFile*    _vieFile; 
  35.         MapWrapper _deviceMap; 
  36.  
  37. }; 

实现:...src\video_engine\main\test\WindowsTest\CaptureDevicePool.cpp

  1. #include "CaptureDevicePool.h" 
  2. #include "map_wrapper.h" 
  3. #include <string.h> 
  4. #include <assert.h> 
  5. #include "critical_section_wrapper.h" 
  6. #include "vie_file.h" 
  7.  
  8. CaptureDevicePool::CaptureDevicePool(VideoEngine* videoEngine): 
  9. _critSect(*CriticalSectionWrapper::CreateCriticalSection()), 
  10. _vieCapture(ViECapture::GetInterface(videoEngine)), 
  11. _vieFile(ViEFile::GetInterface(videoEngine)) 
  12.  
  13. CaptureDevicePool::~CaptureDevicePool(void
  14.     assert(_deviceMap.Size()==0); 
  15.     _vieCapture->Release(); 
  16.     _vieFile->Release(); 
  17.     delete &_critSect; 
  18.  
  19. WebRtc_Word32 CaptureDevicePool::GetCaptureDevice(int& captureId
  20. const char* uniqeDeviceName) 
  21.     CriticalSectionScoped cs(_critSect); 
  22. //创建CriticalSectionScoped cs即立刻进入临界区,它的析构函数保证释
  23. 放临界资源,保护对设备信息MapWrapper _deviceMap的访问 
  24.     DeviceItem* device=NULL; 
  25.      
  26.     for(MapItem* item=_deviceMap.First(); 
  27.         item!=NULL; 
  28.         item=_deviceMap.Next(item)) 
  29.     { 
  30. //Found the device?先从临界资源_deviceMap中查找Device,如果没有的话就定位一个新的DeviceIterm 
  31. if(strcmp(uniqeDeviceName,(static_cast<DeviceItem*>( item->GetItem()))->uniqeDeviceName)==0) 
  32.         { 
  33.             device=static_cast<DeviceItem*>( item->GetItem()); 
  34.             device->refCount++; 
  35.             captureId=device->captureId; 
  36.             return 0; 
  37.         } 
  38.     } 
  39.     //没找到Device定位一个新的Device 
  40.     device = new DeviceItem; 
  41.     strncpy(device->uniqeDeviceName,uniqeDeviceName,255); 
  42.  
  43.  
  44.     // Device does not exist. Create it.并将获取到的设备放到DeviceItem device中去 
  45.     WebRtc_Word32 result=_vieCapture->AllocateCaptureDevice(device->uniqeDeviceName
  46. ,strlen(device->uniqeDeviceName),device->captureId); 
  47.     if(result==0) 
  48.     { 
  49.         //配置设备的属性 
  50.         //CaptureCapability cap; 
  51.         /*cap.height=1080; 
  52.         cap.width=1920; 
  53.         cap.maxFPS=25;     
  54.         cap.interlaced=true;*/ 
  55.      //   result=_vieCapture->StartCapture(device->captureId,cap); 
  56.         //设置捕捉设备初始图片 
  57.         result=_vieFile->SetCaptureDeviceImage(device->captureId,"captureDeviceImage.jpg"); 
  58.     } 
  59.     captureId=device->captureId;            //返回新设备的ID给函数 
  60.     _deviceMap.Insert(captureId,device);//插入到MapWrapper _deviceMap中去 
  61.     device->refCount++;                     //引用加1 
  62.      
  63.     return result; 
  64.  
  65.  
  66. WebRtc_Word32 CaptureDevicePool::ReturnCaptureDevice(int captureId) 
  67.     CriticalSectionScoped cs(_critSect); 
  68.  
  69.     MapItem* mapItem=_deviceMap.Find(captureId); 
  70.     if(!mapItem) 
  71.         return -1; 
  72.  
  73.     DeviceItem* item=static_cast<DeviceItem*> (mapItem->GetItem()); 
  74.     if(!item) 
  75.         return 0; 
  76.     item->refCount--; 
  77.     WebRtc_Word32 result=0; 
  78.  
  79.     if(item->refCount==0) 
  80.     { 
  81.         result=_vieCapture->ReleaseCaptureDevice(captureId); 
  82.          
  83.         _deviceMap.Erase(mapItem); 
  84.         delete item; 
  85.  
  86.     } 
  87.     return result; 

 

(temotemo)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201303/16534.html]
本文出处:CSDN博客 作者:temotemo 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容