Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1072592
  • 博文数量: 243
  • 博客积分: 3053
  • 博客等级: 中校
  • 技术积分: 2975
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-02 21:11
文章分类

全部博文(243)

文章存档

2013年(2)

2012年(20)

2011年(5)

2010年(114)

2009年(102)

我的朋友

分类:

2010-12-08 18:13:09

创建过程所涉及的几个重要函数的算法

 

创建过程所涉及的几个重要函数的算法描述如下:

  1. AllocSlot  

AllocSlot用来分配线程的MFC私有存储空间的槽号。由于该函数要修改全局变量_afxThreadData,所以必须使用m_sect关键段对象来同步多个线程对该函数的调用。

CThreadSlotData::AllocSlot()

{

进入关键段代码(EnterCriticalSection(m_sect);)

搜索m_pSlotData,查找空槽(SLOT)

如果不存在空槽(第一次进入时,肯定不存在)

分配或再分配内存以创建新槽,

指针m_pSlotData指向分配的地址。

得到新槽(SLOT)

标志该SLOT为已用

记录最新可用的SLOT到成员变量m_nRover中。

离开关键段代码(LeaveCriticalSection(m_sect);)

返回槽号

}

  1. GetThreadValue

GetThreadValue用来获取调用线程的第slot个线程局部变量的值。每一个线程局部变量都占用一个且只一个槽位。

CThreadSlotData::GetThreadValue(int slot)

{

//得到一个CThreadData型的指针pData

//pData指向MFC线程私有存储空间。

//m_tlsIndex在_afxThreadData创建时由构造函数创建

pData=(CThreadData*)TlsGetValue(m_tlsIndex),。

如果指针空或slot>pData->nCount, 则返回空。

否则,返回pData

}

  1. SetValue

SetValue用来把调用线程的第slot个线程局部变量的值(指针)存放到线程的MFC私有存储空间的第slot个槽位。

CThreadSlotData::SetValue(int slot, void *pValue)

{

//通过TLS索引得到线程的MFC私有存储空间

pData = (CThreadData*)TlsGetValue(m_tlsIndex)

//没有得到值或者pValue非空且当前槽号,即

//线程局部变量的个数

//大于使用当前局部变量的线程个数时

if (pData NULL or slot > pData->nCount && pValue!=NULL)

{

if pData NULL //当前线程第一次访问该线程局部变量

{

创建一个CThreadData实例;

添加到CThreadSlotData::m_list;

令pData指向它;

}

按目前为止,线程局部变量的个数为pData->pData分配或重分配内存,

用来容纳指向真正线程数据的指针

调用TlsSetValue(pData)保存pData

}

//把指向真正线程数据的pValue保存在pData对应的slot中

pData->pData[slot] = pValue

}

7        管理状态

 

在描述了MFC状态的实现机制之后,现在来讨论MFC的状态管理和相关状态的作用。

1)模块状态切换

模块状态切换就是把当前线程的线程状态的m_pModuleState指针指向即将运行模块的模块状态。

MFC使用AFX_MANAGE_STATE宏来完成模块状态的切换,即进入模块时使用当前模板的模板状态,并保存原模板状态;退出模块时恢复原来的模块状态。这相当于状态的压栈和出栈。实现原理如下。

先看MFC关于AFX_MANAGE_STATE的定义:

#ifdef _AFXDLL

struct AFX_MAINTAIN_STATE

{

AFX_MAINTAIN_STATE(AFX_MODULE_STATE* pModuleState);

~AFX_MAINTAIN_STATE();

protected:

AFX_MODULE_STATE* m_pPrevModuleState;

};

//AFX_MANAGE_STATE宏的定义:

#define AFX_MANAGE_STATE(p) AFX_MAINTAIN_STATE _ctlState(p);

#else // _AFXDLL

#define AFX_MANAGE_STATE(p)

#endif //!_AFXDLL

如果使用MFC DLL,MFC提供类AFX_MAINTAIN_STATE来实现状态的压栈和出栈,AFX_MANAGE_SATATE宏的作用是定义一个AFX_MAINTAIN_STATE类型的局部变量_ctlState。

AFX_MAINTAIN_STATE的构造函数在其成员变量m_pPrevModuleState中保存当前的模块状态对象,并把参数指定的模块状态设定为当前模块状态。所以该宏作为入口点的第一条语句就切换了模块状态。

在退出模块时,局部变量_ctlState将自动地销毁,这导致AFX_MAINTAIN_STATE的析构函数被调用,析构函数把保存在m_pPrevModuleState的状态设置为当前状态。

AFX_MANAGE_SATATE的参数在不同场合是不一样的,例如,

1 DLL的输出函数使用  

AFX_MANAGE_SATATE(AfxGetStaticModuleState());

其中,AfxGetStaticModuleState返回DLL的模块状态afxModuleState。

2 窗口函数使用

AFX_MANAGE_STATE(_afxBaseModuleState.GetData());

其中,_afxBaseModuleState.GetData()返回的是应用程序的全局模块状态。

OLE使用的模块切换方法有所不同,这里不作讨论。

上面讨论了线程执行行不同模块的代码时切换模块状态的情况。在线程创建时怎么处理模块状态呢?

·                     一个进程(使用MFC的应用程序)的主线程创建线程模块状态和进程模块状态,前者是_AFX_THREAD_STATE类的实例,后者是_AFX_BASE_MODULE_STATE类的实例。

 

·                     当进程的新的线程被创建时,它创建自己的线程状态,继承父线程的模块状态。在线程的入口函数_AfxThreadEntry完成这样的处理,该函数的描述见8.5.3节。

 

 

阅读(2026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~