1. Introduction
当我们在用MFC编程的时候,我们经常用到AfxGetApp()来获得当前的CWinApp的Instance。看看MFC的源代码中AfxGetApp()的实现,你会发现AfxGetApp()的实现并不像一般情况下面那样直接:
_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp() { return afxCurrentWinApp; } #define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp |
AfxGetApp()调用的是AfxGetModuleState(),该函数返回一个AFX_MODULE_STATE的指针,其中的一个成员保存着当前的CWinApp的指针。可AfxGetModuleState()的作用又是什么呢?
此外,当我们在开发MFC DLL程序的时候,我们会在每个输出的DLL函数前面加上一句AFX_MANAGE_STATE:
void SomeMFCDllFunction() { AFX_MANAGE_STATE(AfxGetStaticModuleState()) … |
AFX_MANAGE_STATE又是起什么作用呢?从字面上看来,它是Manage某种State,而AfxGetStaticModuleState又是获得State的,那么State究竟是什么呢?
在MFC中,States用来保存某种相关的状态信息,分为下面几类:
1. Process State,和某个单独的进程绑定起来
2. Thread State,和某个单独的线程绑定
3. Module State,和Module相关
前两种State和一般的全局变量十分类似,只是根据需求的不同被绑定于不同的进程/线程,如多线程支持等。而Module State本身比较特别,Module State根据情况的不同,可以是全局,线程,或者进程相关的State,并且可以根据要求快速切换。
2. Process State
常见的Process State有:
1. _AFX_WIN_STATE
2. _AFX_DB_STATE
3. _AFX_DEBUG_STATE
4. _AFX_SOCK_STATE
5. ……
从字面上面可以很容易猜出这些状态的用处。
MFC通过下面的宏来定义Process State:
#define PROCESS_LOCAL(class_name, ident_name) / AFX_COMDAT CProcessLocal<class_name> ident_name; #define EXTERN_PROCESS_LOCAL(class_name, ident_name) / extern CProcessLocal<class_name> ident_name; |
PROCESS_LOCAL用CProcessLocal模板类定义了一个CProcessLocal<class_name>的一个实例作为状态变量,而EXTERN_PROCESS_LOCAL则使在头文件中声明此状态变量。CProcessLocal的定义如下:
class AFX_NOVTABLE CProcessLocalObject { public: // Attributes CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)());
// Implementation CNoTrackObject* volatile m_pObject; ~CProcessLocalObject(); };
template<class TYPE> class CProcessLocal : public CProcessLocalObject { // Attributes public: AFX_INLINE TYPE* GetData() { TYPE* pData = (TYPE*)CProcessLocalObject::GetData(&CreateObject); ENSURE(pData != NULL); return pData; } AFX_INLINE TYPE* GetDataNA() { return (TYPE*)m_pObject; } AFX_INLINE operator TYPE*() { return GetData(); } AFX_INLINE TYPE* operator->() { return GetData(); }
// Implementation public: static CNoTrackObject* AFXAPI CreateObject() { return new TYPE; } };
|
CProcessLocal的作用只是一个Wrapper,Hold一个TYPE*的指针,一旦用户调用GetData来获得这个指针,GetData会首先判断该指针是否为空,如果为空,则创建一个新的实例保存起来,否则返回已有的指针。前提条件是,TYPE必须从CNoTrackObject继承。任何从CNoTrackObject继承的类都拥有自己的new/delete,这样此对象便不会被Debug的内存分配系统所跟踪而误判