ACE服务端编程4:ACE跨平台之运行时初始化和关闭
参考APG里的说法:平台差异及不兼容性的一个特别的方面,是对象的运行时初始化和程序关闭时这些对象的相应析构。
ACE为了明确管理对象的清理,定义了ACE_Object_Manager类,这个类不仅涉及到对象的管理,还与ACE库的初始化与关闭相关。
ACE中应用了大量的设计模式,本篇顺便研究ACE的程序入口函数替换机制分析。
ACE库的初始化与关闭
应用要确保在使用ACE库时正确的初始化和关闭,有以下两种常用方式:
1、使用ACE_TMAIN宏作为程序入口函数;
2、使用ACE::init()和ACE::fini()明确初始化和关闭ACE库。
ACE_TMAIN宏会对程序入口函数进行替换,已在程序执行前和执行后加入初始化代码,对ACE程序入口函数替换机制分析,可以使用编译器展开ACE_TMAIN的代码:
int ace_main_i (int, char *[]);
__declspec (dllimport) int ace_os_main_i (ACE_Main_Base&, int, char *[]);
class ACE_Main : public ACE_Main_Base
{
int run_i (int, char *[]);};
inline int ACE_Main::run_i (int argc, char *argv[]) { return ace_main_i (argc, argv); }
int main (int argc, char *argv[])
{
ACE_Main m; return m.run (argc, argv);
}
int ace_main_i (int argc, ACE_TCHAR * argv[])
{ return 0;
}
可以看到真正的main函数体被替换为:ACE_Main m; return m.run (argc, argv);而程序代码被包括到ace_main_i函数中。
ACE_Main的实例对象m是一个main函数内的栈对象,在main函数开始构造,在函数的结束析构。
ACE_Main类是一个生成类,继承自ACE_Main_Base类,调用其run函数。
ACE_Main_Base在ace/Os_main.h类中定义,代码片段如下:
ACE_Main_Base::ACE_Main_Base ()
{
ACE::init ();
} ACE_Main_Base::~ACE_Main_Base ()
{
ACE::fini ();
} int ACE_Main_Base::run (int argc, char *argv[])
{
return this->run_i (argc, argv);
}
可以看到其构造函数和析构函数也分别通过ACE::init()和ACE::fini()初始化和关闭ACE库。
研究ACE的宏展开也学习一种入口函数替换机制。
跟踪ACE::init()
通过展开ACE_TMAIN宏,发现最终还是在main函数的开始初调用了ACE::init函数,这个函数定义在ace/Init_Ace.cpp中:
int
ACE::init (void)
{
// Don't use ACE_TRACE, because Object_Manager might not have been
// instantiated yet.
// ACE_TRACE ("ACE::init"); ++ACE::init_fini_count_; return ACE_Object_Manager::instance ()->init ();
}
init的函数体非常简单,就是初始化ACE_Object_Manager,也就回到本文开始的主体:这个类不仅涉及到对象的管理,还与ACE库的初始化与关闭相关。
fini函数与此类似,调用了ACE_Object_Manager的清理函数,有兴趣的可以查看源代码。
ACE_Object_Manager
ACE_Object_Manager类之所以与ACE库的初始化和关闭相关,是因为ACE_Object_Manager不仅可以帮助应用能按正确的方式清理对象,ACE库内部的对象管理也依赖于ACE_Object_Manager。
至于ACE_Object_Manager的init函数中的代码可以不必过多深究,主要是实例化一组ACE对象,用以给ACE的内部机制提供支持,并在关闭时销毁这些对象。
ACE_Object_Manager提供了at_exit函数,允许应用向其登记对象,并在关闭时会以登记次序相反的次序销毁所登记的对象。
向ACE_Object_Manager登记的对象必须继承自ACE_Cleanup,并实现cleanup()方法进行清理工作;对于基本类型的对象可以使用at_exit的重载函数传递一个ACE_CLEANUP_FUNC的回调函数。
ACE_Object_Manager的API:http://www.dre.vanderbilt.edu/Doxygen/6.0.0/html/libace-doc/a00355.html
要保证ACE_Object_Manager能够正确的清理对象,必须满足以下两条:
1、永远不要直接调用exit(),让main函数通过return返回(推荐阅读:exit & abort & 析构 & 异常 );
2、确保ACE_Object_Manager成功初始化。
ACE非常有名的单例模式也是关联到ACE_Object_Manager,后期有机会单独写出来。
记录,为更好的自己!
ACE服务端编程4:ACE跨平台之运行时初始化和关闭的更多相关文章
- ACE服务端编程3:ACE跨平台之分配堆内存
ACE服务端编程系列的第三篇,探究ACE解决不同编译器之间分配堆内存的差异. 在ACE的官方示例中会看到大量的ACE_NEW_RETURN,ACE_NEW这样的宏,这是ACE为了消除不同编译器编译的代 ...
- ACE服务端编程2:ACE跨平台之数据类型和宽字符
ACE网络库的主要优势之一就是跨平台,ACE提供了操作系统API和编译器级别的跨平台解决方法,使开发人员不用再去关心操作系统和编译器的差异,但因此也带来了ACE的复杂性. ACE网络库的组织结构主要分 ...
- ACE服务端编程1:使用VS2010编译ACE6.0及从ACE5.6升级的注意事项
ACE是一个跨平台的用于并发通信的C++框架,项目开始时使用的是ACE 5.6发布版,目前最新的ACE版本是6.3.0. 网上一直有一种黑ACE的氛围,主要黑点在于ACE的复杂和作者的背景,结合实际应 ...
- ACE服务端编程5:ACE日志输出和跟踪
服务器程序经常需要在命令行中显示错误消息.状态或者用来跟踪程序的执行路径,最简单的方法是使用printf. ACE提供了更强大日志设施: 1.可以在编译时启用或禁用宏: 2.可以动态的启用或禁用宏: ...
- Linux多线程服务端编程一些总结
能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...
- 《Linux 多线程服务端编程:使用 muduo C++ 网络库》电子版上市
<Linux 多线程服务端编程:使用 muduo C++ 网络库> 电子版已在京东和亚马逊上市销售. 京东购买地址:http://e.jd.com/30149978.html 亚马逊Kin ...
- 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册
<Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...
- 《Linux多线程服务端编程》笔记——多线程服务器的适用场合
如果要在一台多核机器上提供一种服务或执行一个任务,可用的模式有 运行一个单线程的进程 运行一个多线程的进程 运行多个单线程的进程 运行多个多线程的进程 这些模式之间的比较已经是老生常谈,简单地总结 模 ...
- 《Linux多线程服务端编程》笔记——线程同步精要
并发编程基本模型 message passing和shared memory. 线程同步的四项原则 尽量最低限度地共享对象,减少需要同步的场合.如果确实需要,优先考虑共享 immutable 对象. ...
随机推荐
- mysql数据库查询
查询数据指从数据库中获取所需要的数据.查询数据是数据库操作中最常用,也是最重要的操作.用户可以根据自己对数据的需求,使用不同的查询方式.通过不同的查询方式,可以获得不同的数据.MySQL中是使用SEL ...
- 《JavaScript》函数
function foo(a,b){return a+b}//函数申明 var foo=function(){}//函数表达式赋值 var foo=new Function('a','b','retu ...
- Java变量声明,实例化,问题
1.变量在输出前必须实例化,这是因为只有声明,没有分配内存空间 在这种情况下会报错 2.实例化后,尽管没有赋值,可能是默认了吧,但也不会输出null,什么也没有输出 上面的理解可能是错的,a赋值了,就 ...
- Python 变量和常量及数据类型
一.变量的命名 变量由字母.数字和下划线组成.变量的第1个字符必须是字母或下划线. 二.变量的赋值 例: x = 1 三.局部变量 局部变量只能在函数或者代码段内使用. 四.全局变量 在函数之外定义的 ...
- 【最小生成树+LCA】Imperial roads
http://codeforces.com/gym/101889 I 先跑一遍最小生成树,把经过的边和答案记录下来 对于每个询问的边,显然如果处于MST中,答案不变 如果不在MST中,假设这条边连上了 ...
- 团队Alpha冲刺(六)
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...
- 有关rand(),srand()产生随机数学习总结
看到夏雪冬日的有关rand()和srand()产生随机数的总结,挺好的,学习了,然后又有百度其他人的成果,系统总结一下.本文转自夏雪冬日:http://www.cnblogs.com/heyongga ...
- 操作系统之实验二Step1-有序顺序表
实验二Step1-有序顺序表 专业:商业软件工程 班级:商软2班 姓名:甘佳萍 学号:201406114207 实验要求:初始化 输入数组元素个数. 输入n个数,排序输出. 存 ...
- Qt程序打包,自动拷贝依赖文件
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt程序打包,自动拷贝依赖文件 本文地址:http://techieliang.com ...
- form 表单提交类型
multipart/form-data与x-www-form-urlencoded区别 multipart/form-data:既可以上传文件等二进制数据,也可以上传表单键值对,只是最后会转化为一条信 ...