MFC教程(9)-- MFC的进程和线程(1)
2010-03-25 20:35:08 来源:WEB开发网CThreadLocal模板用来声明任意类型的线程私有的变量,因为通过模板可以自动的正确的转化(cast)指针类型。程序员可以使用它来实现自己的线程局部变量,正如MFC实现线程局部的线程状态变量和模块-线程变量一样。
CThrealLocal的成员函数CreateObject用来创建动态的指定类型的对象。成员函数GetData调用了基类CThreadLocalObject的同名函数,并且把CreateObject函数的地址作为参数传递给它。
另外,CThreadLocal模板重载了操作符号“*”、“->”,这样编译器将自动地进行有关类型转换,例如:
_AFX_THREAD_STATE *pStata = _afxThreadState
是可以被编译器接收的。
现在回头来看_afxThreadState的定义:
从以上分析可以知道,THREAD_LOCAL(class_name, ident_name)定义的结果并没有产生一个名为ident_name的class_name类的实例,而是产生一个CThreadLocal模板类(确切地说,是其派生类)的实例,m_nSlot初始化为0。所以,_afxThreadState实质上是一个CThreadLocal模板类的全局变量。每一个线程局部变量都对应了一个全局的CThreadLoacl模板类对象,模板对象的m_nSlot记录了线程局部变量对象的槽号。
进程模块状态afxBaseModuleState
进程模块状态定义如下:
PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)
表示它是一个_AFX_BASE_MODULE_STATE类型的进程局部(process local)的变量。
进程局部变量的实现方法主要是为了用于Win32s下。在Win32s下,一个DLL模块如果被多个应用程序调用,它将让这些程序共享它的全局数据。为了DLL的全局数据一个进程有一份独立的拷贝,MFC设计了进程私有的实现方法,实际上就是在进程的堆(Heap)中分配全局数据的内存空间。
在Win32下,DLL模块的数据和代码被映射到调用进程的虚拟空间,也就是说,DLL定义的全局变量是进程私有的;所以进程局部变量的实现并不为Win32所关心。但是,不是说afxBaseModuleState不重要,仅仅是采用PROCESS_LOCAL技术声明它是进程局部变量不是很必要了。PROCESS_LOCAL(class_name, ident_name)宏展开后如下:
AFX_DATADEF CProcessLocal<class_name> ident_name;
这里,CProcessLocal是一个类模板,从CProcessLocalObject类继承。
CProcessLocalObject和CProcessLocal的定义如下:
class CProcessLocalObject
{
public:
// Attributes
CNoTrackObject* GetData(CNoTrackObject* (AFXAPI*
pfnCreateObject)());
// Implementation
CNoTrackObject* volatile m_pObject;
~CProcessLocalObject();
};
template<class TYPE>
class CProcessLocal : public CProcessLocalObject
{
// Attributes
public:
inline TYPE* GetData()
{
TYPE* pData =(TYPE*)CProcessLocalObject::GetData(&CreateObject);
ASSERT(pData != NULL);
return pData;
}
inline TYPE* GetDataNA()
{ return (TYPE*)m_pObject; }
inline operator TYPE*()
{ return GetData(); }
inline TYPE* operator->()
{ return GetData(); }
// Implementation
public:
static CNoTrackObject* AFXAPI CreateObject()
{ return new TYPE; }
};
类似于线程局部对象,每一个进程局部变量都有一个对应的全局CProcessLocal模板对象。
状态对象的创建
状态对象的创建过程
回顾前一节的三个定义:
CThreadSlotData* _afxThreadData;
THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)
PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)
第一个仅仅定义了一个指针;第二和第三个定义了一个模板类的实例。相应的CThreadSlotData对象(全局)、_AFX_THREAD_STATE对象(线程局部)以及_AFX_BASE_MODULE_STATE对象(进程局部)并没有创建。当然,模块状态对象的成员模块-线程对象也没有被创建。这些对象要到第一次被访问时,才会被创建,这样做会提高加载DLL的速度。
更多精彩
赞助商链接