为了异常安全(swap,share_ptr)——Effecive C++
2017-03-27 21:26
316 查看
互斥锁:
假设我们要在多线程中实现背景图片的控制: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++》相关文章推荐
- 【c++系列12】异常安全之auto_ptr
- C++异常安全、copy and swap
- C++异常安全之std:auto_ptr
- C++中的异常安全、以及copy_and_swap
- 如何编写异常安全的C++代码
- 如何编写异常安全的C++代码
- C++箴言:争取异常安全的代码
- 如何编写异常安全的C++代码
- C++析构函数的使用--异常安全
- 如何编写异常安全的C++代码
- C++箴言:争取异常安全的代码
- share_ptr 实现c++ 句柄引用计数
- 如何编写异常安全的C++代码
- 如何编写异常安全的C++代码
- 如何编写异常安全的C++代码
- C++箴言:考虑支持不抛异常的swap
- 如何编写异常安全的C++代码
- C++ boost的share_ptr传递给普通指针,修改原来的值
- 如何编写异常安全的C++代码
- 如何编写异常安全的C++代码