1.复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为
2.普遍而常见的的RAII class copying行为是:抑制copying,施行引用计数法
第1条的意思是:我们要根据资源的copying行为去选择所用的管理类,
比如,
我之前有个类
class Lock
{
public:
explicit Lock(mutex* pm):mutexPtr(pm){mutexPtr->lock();}
~Lock() {mutexPtr->unlock();}
private:
mutex* mutexPtr;
}
这个类其实就是实现互斥量的锁定和解锁,但是如果要copy呢
1.禁止复制,这对互斥量来说其实还是很合理的
2.采用引用计数,引用计数就是复制时并不增加资源的数量,增加计数,当计数为0时,释放资源
我们这里考虑mutex的copying行为,决定采用shared_ptr嵌套Lock类,定义新的管理类,顺便说下,shared_ptr可以自定义自己的删除器
这是修改后的代码
void unlock(mutex* pm);
class Lock
{
public:
explicit Lock(mutex* pm) :MutexPtr(pm, unlock){ MutexPtr.get()->lock(); }//这里我们把unlock定义为删除器,所以就不需要析构函数了
private:
shared_ptr<mutex> MutexPtr;
};
void unlock(mutex* pm)
{
pm->unlock();
}
再找个例子
#include<windows.h>
#include <iostream>
#include <memory>
#include <string>
#include<process.h>
#include<stdlib.h>
#include<vector>
#include <mutex>
using namespace std;
vector<int> g_vec;
HANDLE g_read, g_write;
//HANDLE hMutex;
mutex mx;
unsigned int WINAPI WorkThreadRead(void* param);
unsigned int WINAPI WorkThreadWrite(void* param);
void unlock(mutex* pm);
class Lock
{
public:
explicit Lock(mutex* pm) :MutexPtr(pm, unlock){ MutexPtr.get()->lock(); }
private:
shared_ptr<mutex> MutexPtr;
};
int main()
{
//hMutex = CreateMutex(NULL, true, NULL);
g_read = (HANDLE)_beginthreadex(NULL, 0, WorkThreadRead, NULL, 0, NULL);
g_write = (HANDLE)_beginthreadex(NULL, 0, WorkThreadWrite, NULL, 0, NULL);
CloseHandle(g_read);
CloseHandle(g_write);
system("pause");
return 0;
}
unsigned int WINAPI WorkThreadRead(void* param)
{
while (true)
{
Lock a(&mx);
//WaitForSingleObject(hMutex, INFINITE);
for (vector<int>::iterator it = g_vec.begin(); it != g_vec.end(); ++it)
{
cout << (*it) << endl;
}
//ReleaseMutex(hMutex);
}
}
unsigned int WINAPI WorkThreadWrite(void* param)
{
srand(GetTickCount());
while (true)
{
Lock a(&mx);
//WaitForSingleObject(hMutex, INFINITE);
if (g_vec.size() > 0)
{
if (rand() % 100 > 50)
{
g_vec.push_back(rand() % 10000);
}
else
{
g_vec.erase(g_vec.begin());
}
}
else
{
g_vec.push_back(rand() % 10000);
}
//ReleaseMutex(hMutex);
Sleep(10);
}
}
void unlock(mutex* pm)
{
pm->unlock();
}
同步顺利时,显示的都是正常的值,不顺利时,显示的是未初始化的值