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,后期有机会单独写出来。


记录,为更好的自己!

posted @ 2015-05-22 23:22  全栈工程狮  阅读(1428)  评论(0编辑  收藏  举报