如下为CMutex的类定义
- class CMutex : public CSyncObject
- {
- DECLARE_DYNAMIC(CMutex)
- // Constructor
- public:
- /* explicit */ CMutex(BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL,
- LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);
- // Implementation
- public:
- virtual ~CMutex();
- BOOL Unlock();
- };
构造函数如下
- CMutex::CMutex(BOOL bInitiallyOwn, LPCTSTR pstrName,
- LPSECURITY_ATTRIBUTES lpsaAttribute /* = NULL */)
- : CSyncObject(pstrName)
- {
- m_hObject = ::CreateMutex(lpsaAttribute, bInitiallyOwn, pstrName);
- if (m_hObject == NULL)
- AfxThrowResourceException();
- }
m_hObject为基类的成员变量,其实也就是Handle了,这里可以创建或者获得一个Mutex的Handle.若m_hObject == NULL(没有获得Mutex的Handle,在已存在Mutex的情况下也是能返回一个已存在的Handle的),抛出异常。具体MSDN CreateMutex.
再看看Lock函数:从基类CSyncObject继承
- BOOL CSyncObject::Lock(DWORD dwTimeout)
- {
- DWORD dwRet = ::WaitForSingleObject(m_hObject, dwTimeout);
- if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED)
- return TRUE;
- else
- return FALSE;
- }
调用WaitForSingleObject api,dwTimeout默认为INFINITE,根据WaitForSingleObject返回的结果,正常取得访问权限返回OR超时返回,返回TRUE OR FALSE
再看UnLock函数
- BOOL CMutex::Unlock()
- {
- return ::ReleaseMutex(m_hObject);
- }
这里是UnLock函数,简单地调用 ReleaseMutex释放拥有的Mutex对象.
那么Handle从哪里释放呢?
- CSyncObject::~CSyncObject()
- {
- if (m_hObject != NULL)
- {
- ::CloseHandle(m_hObject);
- m_hObject = NULL;
- }
- }
基类的析构函数释放了Handle,而Mutex类中的析构函数没有具体实现.
接下来说一个值得注意的地方:
注意从Mutex构造函数的初始化列表中对基类进行初始化传入的pstrName,被赋值给了m_strName,而这是一个只有在Debug版本下才有的成员变量,估计是帮助调试用的——互斥对象名在系统内核中,用一个成员变量作为拷贝可以方便查看互斥对象名,注意Release版本中无此变量.
- CSyncObject::CSyncObject(LPCTSTR pstrName)
- {
- UNUSED(pstrName); // unused in release builds
- m_hObject = NULL;
- #ifdef _DEBUG
- m_strName = pstrName;
- #endif
- }
给一个简单的使用示例..
- #include <iostream>
- #include <afxmt.h>
- using namespace std;
- CMutex g_Mutex(FALSE, __T("something different"), NULL);
- DWORD WINAPI ThreadFunc(LPVOID);
- int main()
- {
- HANDLE l_hChildThread;
- l_hChildThread = (HANDLE)::CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
- g_Mutex.Lock();
- cout<<"通知子线程开始工作"<<endl;
- system("pause");
- g_Mutex.Unlock();;
- WaitForSingleObject(l_hChildThread, INFINITE);
- CloseHandle(l_hChildThread);
- cout<<"子线程工作完成"<<endl;
- return 0;
- }
- DWORD WINAPI ThreadFunc(LPVOID)
- {
- g_Mutex.Lock();
- cout<<"子线程工作中..."<<endl;
- Sleep(1000);
- g_Mutex.Unlock();
- return 0;
- }
之所以写这篇blog,是因为被CSingleLock弄的有点概念不清,后面明白了,CSingleLock只是进行了再一次的封装。举个例子。有点类似autoptr,弄一层封装,用于解决下面这样的问题,若函数返回点很多,这样写会让人抓狂.
- g_Mutex.Lock();
- if (false)
- {
- g_Mutex.Unlock();
- return false;
- }
- g_Mutex.Unlock();
如果用CSingleLock则是这样
- CSingleLock(&g_Mutex, TRUE);
- if (false)
- {
- return false;
- }
先看下CSingleLock的构造函数:首先进行运行时类型识别,是否CSyncObject类型,此外还将Mutex的(或者Event等等的)Handle传递给CSingleLock对象.并用m_pObject成员变量拷贝pObject指针,用以调用CMutex CEvent等等的Lock Unlock函数.若bInitialLock设置为TRUE,则省去了调用Lock这一步.构造函数中替你调用了.
- CSingleLock::CSingleLock(CSyncObject* pObject, BOOL bInitialLock)
- {
- ASSERT(pObject != NULL);
- ASSERT(pObject->IsKindOf(RUNTIME_CLASS(CSyncObject)));
- if(pObject == NULL)
- AfxThrowInvalidArgException();
- m_pObject = pObject;
- m_hObject = pObject->m_hObject;
- m_bAcquired = FALSE;
- if (bInitialLock)
- Lock();
- }
如下为,CSingleLock的析构函数,调用了Unlock那么,CSingleLock局部对象l_oSingleLock超出其作用域时,将调用l_oSingleLock的析构函数释放对CMutex CEvent CSemaphore的所有权, CSingleLock不但起到了一个autoptr的作用,还通过封装的方式让CMutex CEvent的使用方式一致.
- _AFXMT_INLINE ::CSingleLock::~CSingleLock()
- { Unlock(); }
- 上一篇:GetBuffer 与 ReleaseBuffer
- 下一篇:关于工作的一些碎碎念