互斥锁:

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

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. C语言第一次博客作业---顺序机构基础练习

    一.PTA实验作业 题目1.温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代 ...

  2. js计时功能

    //个位秒加 function time4jia() { //分钟60为上限 所有加停止 if (sz(a('time1').innerHTML) == 6) { return; } var m4 = ...

  3. 单向链表在O(1)时间内删除一个节点

    说删链表节点,第一时间想到就是遍历整个链表,找到删除节点的前驱,改变节点指向,删除节点,但是,这样删除单链表的某一节点,时间复杂度就是O(n),不符合要求: 时间复杂度是O(n)的做法就不说了,看看O ...

  4. Twisted UDP编程技术

    实战演练1:普通UDP UDP是一种无连接对等通信协议,没有服务器和客户端概念,通信的任何一方均可通过通信原语直接和其他方通信 1.相对于TCP,UDP编程只需定义DatagramProtocol子类 ...

  5. bzoj千题计划271:bzoj4869: [六省联考2017]相逢是问候

    http://www.lydsy.com/JudgeOnline/problem.php?id=4869 欧拉降幂+线段树,每个数最多降log次,模数就会降为1 #include<cmath&g ...

  6. Codechef March Challenge 2014——The Street

    The Street Problem Code: STREETTA https://www.codechef.com/problems/STREETTA Submit Tweet All submis ...

  7. 数据结构与算法 —— 链表linked list(01)

    链表(维基百科) 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储, ...

  8. JAVA_SE基础——14.循环结构语句

    建议有些基础的同学阅读,0基础可能会有些困难(最好看正文配合基础课本的例子) 所谓循环语句主要就是在满足条件的情况下反复执行某一个操作.Java提供了3种常用的循环语句,分别为for循环语句.whil ...

  9. 求解数独难题, Sudoku问题(回溯)

    Introduction : 标准的数独游戏是在一个 9 X 9 的棋盘上填写 1 – 9 这 9 个数字,规则是这样的: 棋盘分成上图所示的 9 个区域(不同颜色做背景标出,每个区域是 3 X 3 ...

  10. Appium+python测试app实例

    Appium和selenium差不到,只是一个用于测web,一个用于测APP.下面记录一下我搭的测试框架,同样是基于PO模式,用的unittest. 最后测试报告如下: 1.1      代码结构 这 ...