条款29:为“异常安全”而努力是值得的

/**********条款14设计的互斥器***************
#include <boost/shared_ptr.hpp>
class Mutex;
class Lock
{
public:
explicit Lock(Mutex* pm)
: mutexPtr(pm, unlock) //unlock为函数删除器
{
lock(mutexPtr.get());
}


void lock(Mutex* pm);
void unlock(Mutex* pm);


private:
std::tr1::shared_ptr<Mutex> mutexPtr;
};
********************************************/


/*****************分析示例***********************
#include <iostream>
class Mutex;
class Image;
class PrettyMenu
{
public:
void changeBackground(std::istream& imgSrc);
private:
Mutex mutex;
Image* bgImage;
int imageChanges;
};


void PrettyMenu::changeBackground(std::istream& imgSrc)
{
lock(&mutex); //取得互斥器
delete bgImage; //删除老图片
++imageChanges; //修改次数加1
bgImage = new Image(imgSrc); //创建新背景
unlock(&mutex); //释放互斥器
}


//从“异常安全性”的角度说这个函数很差,异常安全有两个条件
//1、 不泄漏任何资源。一旦new Image导致异常,对unlock的调用就不会执行,于是互斥器就永远被把持住了
//2、 不允许数据败坏。new Image异常,则bgImage就指向了一个已被删除的对象, imageChanges已被累加,并且没有新的图像生成。


//修改1,引前条款14互斥器, 解决资源泄漏的问题
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
Lock ml(&mutex);
delete bgImage;
++imageChanges;
bgImage = new Image(imgSrc);
}


//异常安全提供以下三个安全保证之一
//1、基本承诺:如果异常抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或数据结构会因此而破坏, 所有对象都处于一种内部前后一致的状态
//2、强烈保证:如果异常抛出,程序状态不改变。如果函数成功就完全成功,如果失败,就会回复到“函数调用前”的状态
//3、不抛出(nothrow)保证:绝不抛出异常,因为它们总是能够完成它们原先承诺的功能。作用于内置类型(如ints, 指针)身上的所有操作都提供nothrow保证。


//修改2,几乎足够提供强列的安全保证
//美中不足的是参数imgSrc,发生异常时可能input stream的read marker已被移走,对程序其作部分可能造成影响
//所以在这个方面程序只提供了基本保证
class PrettyMenu
{
...
std::tr1::shared_ptr<Image> bgImage;
...
};
void PrettyMenu::changeBackground(std::istream& imgSrc)
{
Lock ml(&mutex);
bgImage.reset(new Image(imgSrc)); //不需要删除旧图片,已由智能指针自动处理
++imageChanges;
}


//修改3,copy and swap, 将对象所有成员数据放到别一个对象中,复制该数据对象然后修改,最后置换
//该方式需要占用很多空间和时间,所以并非在任何时刻都显得实际
struct PMImpl
{
std::trl::shared_ptr<Image> bgImage;
int imageChanges;
};
class PrettyMenu
{
...
private:
Mutex mutex;
std::trl::shared_ptr<PMImpl> pImpl;
};
void PrettyMenu::changeBackground(istream& imgSrc)
{
using std::swap;
Lock ml(&mutex);
std::tr1::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl));
pNew->bgImage.reset(new Image(imgSrc)); //修改副本
++pNew->imageChanges;
swap(pImpl, pNew); //置换数据,释放mutex
}


//copy and swap是对对象做出“全有或全无”的一个很好办法,但一般而言它并不保证对整个函数做出强烈异常安全的保证。
//示例:
void someFun()
{
... //copy后修改
f1(); //如果f1 f2不能提供强烈保证
f2(); //则someFun很难提供强烈异常安全
... //swap
}
*************************************************/

//!!! 函数提供的“异常安全保证”通常最高只等于其调用的函数的安全性最低的那个
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值