多线程下的内存管理与单线程下是完全不同的,因为heap是一个可以被全局改动的资源,所以所有的线程都有可能去访问这一资源,这回导致很多的race_conditions。

 
当operator new未取得想要的内存的时候,会调用一个用户指定的处理函数,new_handler。 这个函数可以使用set_new_handler来进行指定。

 namespace std{
typedef void(*new_handler)();//没有参数以及返回值
new_handler set_new_handler(new_handler p) throw();
}
当operator new无法满足内存申请条件的时候,其就会不停的调用new-handler函数,所以说一个设计良好的new-handler应该需要满足下面的要求:
    让更多的内存被使用
    当当前的handler无法满足条件的时候,安装另一个new-handler.
    卸除new_handler,将null指针传给set_new_handler,,此时operator new 在无法分配内存的时候就会抛出异常
    抛出bad_alloc异常:这样的异常会被传播到内存的索求处
    不返回:调用abort或者exit
 
 
当需要以不同的方式去处理不同的class内存分配失败的情况的时候,应该为相应的特殊的class提供自己的set_new_handler以及operator_new。这样operator new会在分配内存的时候确保使用class专属的new_handler替代global的new handler.
 
一个Widget分配资源的简单例子:

 class NewHandlerHolder{
public:
explicit NewHandlerHolder(std::new_handler nh)
:handler(nh){}
~NewHandlerHolder()
std::set_new_handler(handler); //将状态恢复到之前的状态
private:
new_handler handler;
NewHandlerHolder(const NewHandlerHolder &); //禁止这两种操作
NewHandlerHolder & operator(const NewHandlerHolder &);
};

上面这个就可以被自定义的一个类所使用了:

 void * Widget::operator new(std::size_t size) throw (std::bad_alloc)
{
NewHandlerHolder h(std::set_new_handler(currentHandler));//使用上面的RAII将handler资源正确的管理。
return ::operator new(size);//使用自定义的new
}

实际上,可以将上面的NewHandlerHolder设计成为一个基类模板,这样derived_class科技继承他们需要的set_new_handler以及operator_new,template用于保证每一个derived_class获得一个实体互异的currentHandler成员变量。下为这个模板:

 template<typename T>   //这里的typename T 并未被使用,作用下面会说
class NewHandlerSupport{
public:
static std::new_handler set_new_handler(std::new_handler p) throw();
static void * operator new(std::size_t size) throw(std::bad_alloc);
...
private:
static std::new_handler currentHandler;
};
template<typename T>
static std::new_handler
NewHandlerSupport<T> set_new_handler(std::new_handler p) throw()
{
std::new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}
template<typename T>
static void *
NewHandlerSupport<T>::operator new(std::size_t size) throw(std::bad_alloc)
{
NewHandlerHolder h(std::set_new_handler(currentHandler));
return ::operator(size);//调用全局的operatornew,防止递归的调用自己。
}

有了这个模板,那么为Widget提供专属的set_new_handler以及operator都是很容易的了。继承上面的模板并特例化就可以了:

 class Widget : public NewHandlerSupport<Widget>{
...
};
这样就有了专属的set_new_handler以及operator new。
上买了的typename T 没有被使用,实际上也不需要, 这个T的目的只是为了使得不同的继承自NewHandlerSupport的子类有着其不同的实例函数。(主要是为了static变量,currentHandler)。T只是用来区分不同的derived_class. (因为上面T实例化成了Widget)
 
还有就是关于nothrow的问题,使用new (std::nothrow) Widget不会在new上产生异常,只会返回一个null指针,但是如果new正常还有可能在构造过程中产生异常,因此依然没有异常保证。没事不要用new (std::nothrow) sth;
 
小结:
    set_new_handler允许用户指定一个函数在内存无法分配时调用
    Nothrow new只能保证new不抛异常,构造仍然得不到保证。
 

最新文章

  1. 装tomcat和nginx心得
  2. IAR EW8051-8.10.4安装及破解方法
  3. selenium如何解决window安全验证问题
  4. 浅谈JS面向对象之创建对象
  5. BZOJ3238 [Ahoi2013]差异
  6. [Linux] Ubuntu Server 12.04 LTS 平台上搭建WordPress(Nginx+MySQL+PHP) Part IV
  7. 【编程基础】const与#define的区别
  8. [置顶] android利用jni调用第三方库——第二篇——编写库android程序直接调用第三方库libhello.so
  9. [转]Libev源码分析 -- 整体设计
  10. Servlet程序开发-- 取得其他内置对象
  11. Storm(2015.08.12笔记)
  12. ABP官方文档翻译 9.1 EntityFramework集成
  13. (五)java运算
  14. Filecoin官方更新: Q4工作进展和2018年工作计划
  15. 盒模型的垂直居中css
  16. MySQL学习8 - 数据的增删改
  17. Python_Mix*re模块基础方法,进阶,正则表达式的使用
  18. Thread线程相关方法详解
  19. C# 创建 写入 读取 excel
  20. MVC3学习:利用mvc3+ajax检测用户是否被注册

热门文章

  1. 021-Spring Boot 测试,Junit方式使用,mock方式,Controller测试
  2. 判断数A和数B中有多少个位不相同
  3. 利用onresize使得div可以随着屏幕大小而自适应的代码
  4. 17南宁区域赛 I - Rake It In 【DFS】
  5. arcgis for flex map遮罩
  6. centos中安装php7
  7. vagrant搭建
  8. R的基础学习之数据结构
  9. streambase一些疑难杂症
  10. jQuery 获取jsp页面中用iframe引入的jsp页面中的值