1、
1 class CMutex::PrivateData 2 { 3 public: 4 HANDLE hEvent; 5 }; 6 7 ////// 8 CMutex::CMutex() 9 { 10 d = new CMutex::PrivateData(); 11 d->hEvent = CreateEvent( 12 NULL, // default security attributes 13 FALSE, //bManualReset 14 TRUE, // signaled 15 NULL); // unnamed object 16 } 17 18 CMutex::~CMutex() 19 { 20 SetEvent(d->hEvent); 21 CloseHandle(d->hEvent); 22 } 23 24 void CMutex::lock() 25 { 26 WaitForSingleObject(d->hEvent, INFINITE); 27 } 28 29 bool CMutex::tryLock(int timeout) 30 { 31 DWORD dwWaitResult = WaitForSingleObject(d->hEvent, timeout); 32 return (dwWaitResult == WAIT_OBJECT_0); 33 } 34 35 36 void CMutex::unlock() 37 { 38 SetEvent(d->hEvent); 39 }
CMutex类。生成一个事件对象,提供等待和开的接口(互斥事件)。
用于WFSOpen、WFSStartUp函数的多次调用控制,windows下采用下面的方法
可以在一个线程的执行函数中创建一个事件对象,然后观察它的状态,“有信号”(触发,开,true),如果是”无信号”(未触发,关,false)就让该线程睡眠,这样该线程占用的CPU时间就比较少
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes, // SD 一般为空
BOOL bManualReset, // reset type 事件是自动复位(false)还是人工复位(true)
BOOL bInitialState, // initial state 初始状态,有信号(true),无信号(false)
LPCTSTR lpName // object name 事件对象名称 );
******
代码中CreateEvent默认初始状态是true即有信号状态,当执行waitForSingleObject时不会等待。 并且是自动复位的,在执行waitForSingleObject之后会变成未触发(无信号)状态。
******
WaitForSingleObject(d->hEvent, INFINITE);
原型WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD
//生成事件对象后,通过调用此函数来让线程进入等待状态
//hObject 指向同步对象的指针
//等待同步对象变成”有信号“前的等待时间,如果想要线程一直等待,请把该参数设为INFINITE(该值等于0xffffffff)
SetEvent(d->hEvent) //设置为“有信号”
首先CMutex的构造函数中,CreateEvent是默认触发状态,并且是自动复位模式。
然后在startup中,调用d->m_bStartUp.tryLock(0)、这个接口会调用WaitForSingleObject, 自动模式下执行Wait之后会将事件改变为未触发状态,由于传入0,本次调用会返回WAIT_OBJECT,这个判断是true不会进入if执行。
然后第二次调用d->m_bStartUp.tryLock(0),如果之前没有做setEvent变为触发,则会返回false。 同理d->m_bStartOrCleaning这个对象用来判断异步接口调用也是类似原理
因为线程的句柄在线程运行时是未触发的,线程结束运行,句柄处于触发状态。 所以可以用WaitForSingleObject()来等待一个线程结束运行。
1 #include "mutex.h" 2 3 #ifndef Q_OS_WIN 4 5 #include<stdio.h> 6 #include <pthread.h> 7 #include <unistd.h> 8 9 class CMutex::PrivateData 10 { 11 public: 12 pthread_mutex_t mutex; 13 bool bInitialized; 14 }; 15 16 ////// 17 CMutex::CMutex() 18 { 19 d = new CMutex::PrivateData(); 20 d->bInitialized = (pthread_mutex_init(&d->mutex, NULL) == 0); 21 } 22 23 CMutex::~CMutex() 24 { 25 if(d->bInitialized){ 26 pthread_mutex_unlock(&d->mutex); 27 pthread_mutex_destroy(&d->mutex); 28 } 29 } 30 31 void CMutex::lock() 32 { 33 if(!d->bInitialized){ 34 return; 35 } 36 pthread_mutex_lock(&d->mutex); 37 } 38 39 bool CMutex::tryLock(int timeout) 40 { 41 if(!d->bInitialized){ 42 return false; 43 } 44 45 int ret = pthread_mutex_trylock(&d->mutex); 46 if(ret == 0){ 47 return true; 48 } 49 50 while(timeout > 0){ 51 --timeout; 52 usleep(1000); 53 ret = pthread_mutex_trylock(&d->mutex); 54 if(ret == 0){ 55 return true; 56 } 57 } 58 return false; 59 } 60 61 void CMutex::unlock() 62 { 63 if(!d->bInitialized){ 64 return; 65 } 66 pthread_mutex_unlock(&d->mutex); 67 } 68 69 70 #endif //Q_OS_UNIX
linux环境中采用下面方法 pthread_mutex_init(//此接口在CMutex构造函数中调用,用于互斥锁的初始化
pthread_mutex_t *restrict mutex, //互斥锁
const pthread_mutexattr_t *restrict attr //互斥锁的属性,为空则使用默认属性 )
初始化成功执行后,互斥锁被初始化为未锁状态;
初始化成功bInitialized = true; pthread_mutex_trylock(&mymutex) 此接口会尝试锁定mymutex,如果该互斥锁已经锁定则返回一个非0的错误码; 如果该互斥锁没有锁定则返回0,表示锁定成功。 当第一次调用trylock(0)之后,返回的是true;若不进行unlock,则之后调用trylock(0)都会返回false。 用来管理判断StartUp是否执行,以及open函数是否执行