得到了线程状态的值后,通过它得到模块状态m_pModuleState。如果m_pModuleState为空,表明该线程状态是才创建的,其许多成员变量还没有赋值,程序的进程模块状态还没有被创建。于是调用函数_afxBaseModule.GetData,导致进程模块状态被创建。
图9-7的下面一个虚线框表示了CProcessLocalObject::GetData的创建过程:
_afxBaseModule首先检查成员变量m_pObject是否空,如果非空就返回它,即进程模块状态指针;否则,在堆中创建一个动态的_AFX_BASE_MODULE_STATE对象,返回。
从上述两个GetData的实现可以看出,CThreadLocal模板对象负责线程局部变量的创建和管理(查询,修改,删除);CProcessLocal模板对象负责进程局部变量的创建和管理(查询,修改,删除)。
模块-线程状态的创建
模块状态的成员模块-线程状态m_thread的创建类似于线程状态的创建:当第一次访问m_thread所对应的CThreadLocal模板对象时,给m_thread分配MFC线程局部存储的私有槽号m_nSlot,并动态地创建_AFX_MODULE_THREAD_STATE对象,保存对象指针在m_nSlot槽中。
创建过程所涉及的几个重要函数的算法
创建过程所涉及的几个重要函数的算法描述如下:
AllocSlot
AllocSlot用来分配线程的MFC私有存储空间的槽号。由于该函数要修改全局变量_afxThreadData,所以必须使用m_sect关键段对象来同步多个线程对该函数的调用。
CThreadSlotData::AllocSlot()
{
进入关键段代码(EnterCriticalSection(m_sect);)
搜索m_pSlotData,查找空槽(SLOT)
如果不存在空槽(第一次进入时,肯定不存在)
分配或再分配内存以创建新槽,
指针m_pSlotData指向分配的地址。
得到新槽(SLOT)
标志该SLOT为已用
记录最新可用的SLOT到成员变量m_nRover中。
离开关键段代码(LeaveCriticalSection(m_sect);)
返回槽号
}
GetThreadValue
GetThreadValue用来获取调用线程的第slot个线程局部变量的值。每一个线程局部变量都占用一个且只一个槽位。
CThreadSlotData::GetThreadValue(int slot)
{
//得到一个CThreadData型的指针pData
//pData指向MFC线程私有存储空间。
//m_tlsIndex在_afxThreadData创建时由构造函数创建
pData=(CThreadData*)TlsGetValue(m_tlsIndex),。
如果指针空或slot>pData->nCount, 则返回空。
更多内容请看PCdog.com--Fireworks教程 PPT教程 电脑入门教程专题
