互斥锁:

假设我们要在多线程中实现背景图片的控制:

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;
bgImage=new Image(imgSrc);
unlock(&mutex);
}

但是上面这些会遇到两个问题:

  • 如果 new Image(imgSrc)发生了异常,那么unlock就不会被执行,会被一直锁住
  • 发生上面异常,imageChanges也被累加,但实际上新的图片没有被安装

对于第一个问题:

被及时释放的互斥锁:

share_ptr我们可以指定它的删除器,所以可以在删除器中释放互斥锁.

如此即使是发生了异常,互斥锁也能够被及时的释放。

class Lock{
public:
explicit Lock(Mutex* mu):mutexPtr(mu,unlock)//以某个Mutex初始化,unlock作为删除其
{
lock(mutexPtr);
}
private:
shared_prt<Mutex> mutexPtr;
};

如果通过一个Lock类,然后在析构函数阶段进行 unlock也可以避免这个问题。但是这样的类进行复制的时候

可能存在很多不合理的问题。

如果希望保存资源直到最后一个对象消失,并且在复制的时候是引用计数,可以使用上面这种情况。


对于第二个问题:

swap的 全or无:

struct PMImpl{
std::tr1::shared_ptr<Image> bgImage;
int imageChanges;
};
class PrettyMenu{
……
private:
Mutex mutex;
std::tr1::shared_ptr<PMImpl> pImpl;
}; void PrettyMenu::changeBackground(std::istream& imgSrc)
{
using std::swap;//**条款**25
Lock m1(&mutex);
std::tr1::shared_ptr<PMImpl> pNew(new PMImpl(*pImpl));
pNew->bgImage.reset(new Image(imgSrc));;//修改副本
++pNew->imageChanges;
swap(pImpl,pNew);
}

我们可以先弄一个副本,在进行完所有的操作之后,再与目标对象进行交换。

从而实现: 要不然就不处理,不然就全部处理完。

所以我们需要一个 不会抛出异常的swap操作。


参考:

《Effective C++》

为了异常安全(swap,share_ptr)——Effecive C++的更多相关文章

  1. 【25】考虑写出一个不抛异常的swap函数

    1.swap交换对象值,std提供了实现方法模版的实现,它的实现是交换对象值. namespace std { template<typename T> void swap(T& ...

  2. [Effective C++ --025]考虑写出一个不抛异常的swap函数

    引言 在我的上一篇博客中,讲述了swap函数. 原本swap只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来处理自我赋值可能性. 一.swap函数 标准库的swap函数如下: namespa ...

  3. EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数

    记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...

  4. Effective C++:条款25:考虑写出一个不抛异常的swap函数

    (一) 缺省情况下swap动作可由标准程序库提供的swap算法完毕: namespace std { template<typename T> void swap(T& a, T& ...

  5. 考虑实现一个不抛异常的swap

    Effective C++:参考自harttle land 类的swap实现与STL容器是一致的:提供swap成员函数, 并特化std::swap来调用那个成员函数. class Widget { p ...

  6. Effective C++ -----条款25:考虑写出一个不抛异常的swap函数

    当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常. 如果你提供一个member swap,也该提供一个non-member swap用来调用前者.对于cla ...

  7. 《Effective C++》item25:考虑写出一个不抛异常的swap函数

    std::swap()是个很有用的函数,它可以用来交换两个变量的值,包括用户自定义的类型,只要类型支持copying操作,尤其是在STL中使用的很多,例如: int main(int argc, _T ...

  8. Effective C++ Item 25 考虑写出一个不抛异常的swap函数

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛 ...

  9. 不抛异常的swap函数

    namespace AStuff{ template<typename T> class A { public: void swap(A *other) { using std::swap ...

随机推荐

  1. 51Nod P1100 斜率最大

    传送门: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1100 由于2 <= N <= 10000, 所以 ...

  2. Python——cmd调用(os.system阻塞处理)

    os.system(返回值为0,1,2) 0:成功 1:失败 2:错误 os.system默认阻塞当前程序执行,在cmd命令前加入start可不阻塞当前程序执行. 例如: import os os.s ...

  3. 不允许用(a+b)/2这种方式求两个数的均值;如下程序在Linux和32位集成开发环境中运行

    #define MAX(a,b) ((a)>(b)?(a):(b)) #include<stdio.h> int main() { int a = 10; int b = 20; i ...

  4. js window

    window对象: browser object mode :bom对象. bom提供了独立于内容而与浏览器窗口进行交互的对象. bom主要用于管理窗口与窗口之间的通讯,因此其核心对象是window ...

  5. Angular组件——组件生命周期(二)

    一.view钩子 view钩子有2个,ngAfterViewInit和ngAfterViewChecked钩子. 1.实现ngAfterViewInit和ngAfterViewChecked钩子时注意 ...

  6. redis入门(04)redis的数据类型

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 1.String(字符串) ...

  7. Groovy入门(2-2)Groovy的eclipse插件安装

    1.安装eclipse插件 启动eclipse,点击help -> Install New Software... 在弹出的窗口中点击:Add... Groovy插件的地址:http://dis ...

  8. linux centos6.8 下安装mysql 步骤

    安装环境:vmware12.centos6.8.centos中配置阿里云数据元 1.下载mysql 运行: sudo yum -y install mysql-server 如果下载失败,可以卸载重新 ...

  9. kafka之zookeeper 节点

    1.zookeeper 节点 kafka 在 zookeeper 中的存储结构如下图所示:

  10. keepalive配置支持ipv6、ipv4双棧支持

    因公司业务需要,keepalived需要同时支持ipv6和ipv4 keepalived版本1.2.23. keepalived 配置: 重点:ipv6的虚IP配置在 virtual_ipaddres ...