MFC的状态.docx

上传人:b****4 文档编号:6690109 上传时间:2023-05-10 格式:DOCX 页数:12 大小:39.79KB
下载 相关 举报
MFC的状态.docx_第1页
第1页 / 共12页
MFC的状态.docx_第2页
第2页 / 共12页
MFC的状态.docx_第3页
第3页 / 共12页
MFC的状态.docx_第4页
第4页 / 共12页
MFC的状态.docx_第5页
第5页 / 共12页
MFC的状态.docx_第6页
第6页 / 共12页
MFC的状态.docx_第7页
第7页 / 共12页
MFC的状态.docx_第8页
第8页 / 共12页
MFC的状态.docx_第9页
第9页 / 共12页
MFC的状态.docx_第10页
第10页 / 共12页
MFC的状态.docx_第11页
第11页 / 共12页
MFC的状态.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

MFC的状态.docx

《MFC的状态.docx》由会员分享,可在线阅读,更多相关《MFC的状态.docx(12页珍藏版)》请在冰点文库上搜索。

MFC的状态.docx

MFC的状态

9.MFC的状态

MFC定义了多种状态信息,这里要介绍的是模块状态、进程状态、线程状态。

这些状态可以组合在一起,例如MFC句柄映射就是模块和线程局部有效的,属于模块-线程状态的一部分。

1.模块状态

这里模块的含义是:

一个可执行的程序或者一个使用MFCDLL的DLL,比如一个OLE控件就是一个模块。

一个应用程序的每一个模块都有一个状态,模块状态包括这样一些信息:

用来加载资源的Windows实例句柄、指向当前CWinApp或者CWinThread对象的指针、OLE模块的引用计数、Windows对象与相应的MFC对象之间的映射。

只有单一模块的应用程序的状态如图9-1所示。

m_pModuleState指针是线程对象的成员变量,指向当前模块状态信息(一个AFX_MODULE_STATE结构变量)。

当程序运行进入某个特定的模块时,必须保证当前使用的模块状态是有效的模块状态──是这个特定模块的模块状态。

所以,每个线程对象都有一个指针指向有效的模块状态,每当进入某个模块时都要使它指向有效模块状态,这对维护应用程序全局状态和每个模块状态的完整性来说是非常重要的。

为了作到这一点,每个模块的所有入口点有责任实现模块状态的切换。

模块的入口点包括:

DLL的输出函数;OLE/COM界面的成员函数;窗口过程。

在讲述窗口过程和动态链接到MFCDLL的规则DLL时,曾提到了语句AFX_MANAGE_STATE(AfxGetStaticModuleState()),它就是用来在入口点切换模块状态的。

其实现机制将在后面9.4.1节讲解。

多个模块状态之间切换的示意图如图9-2所示。

图9-2中,m_pModuleState总是指向当前模块的状态。

2.模块、进程和线程状态的数据结构

MFC定义了一系列类或者结构,通过它们来实现状态信息的管理。

这一节将描述它们的关系,并逐一解释它们的数据结构、成员函数等。

1.层次关系

图9-3显示了线程状态、模块状态、线程-模块状态等几个类的层次关系:

线程状态用类_AFX_THREAD_STATE描述,模块状态用类AFX_MODULE_STATE描述,模块-线程状态用类AFX_MODULE_THREAD_STATE描述。

这些类从类CNoTrackObject派生。

进程状态类用_AFX_BASE_MODULE_STATE描述,从模块状态类AFX_MODULE_STATE派生。

进程状态是了一个可以独立执行的MFC应用程序的模块状态。

还有其他状态如DLL的模块状态等也从模块状态类_AFX_MODULE_STATE派生。

图9-4显示了这几个类的交互关系。

从图9-4可以看出:

首先,每个线程有一个线程状态,线程状态的指针m_pModuleState和m_pPreModuleState分别指向线程当前运行模块的状态或前一运行模块的状态;其次,每一个模块状态都有一个线程局部的变量用来存储模块-线程状态。

下面各小节列出状态信息管理所涉及的各个类的定义。

2.CNoTrackObject类

在图9-3中,CnoTrackObject是根类,所有状态类都是从它这里派生的,其定义如下:

classCNoTrackObject

{

public:

void*PASCALoperatornew(size_tnSize);

voidPASCALoperatordelete(void*);

#ifdefined(_DEBUG)&&!

defined(_AFX_NO_DEBUG_CRT)

void*PASCALoperatornew(size_tnSize,LPCSTR,int);

#endif

virtual~CNoTrackObject(){}

};

该类的析构函数是虚拟函数;而且,CNoTrackObject重载new操作符用来分配内存,重载delete操作符号用来释放内存,内部通过LocalAlloc/LocalFree提供了一个低层内存分配器(Low_levelalloctor)。

3.AFX_MODULE_STATE类

AFX_MODULE_STATE类的定义如下:

//AFX_MODULE_STATE(globaldataforamodule)

classAFX_MODULE_STATE:

publicCNoTrackObject

{

public:

#ifdef_AFXDLL

AFX_MODULE_STATE(BOOLbDLL,WNDPROCpfnAfxWndProc,

DWORDdwVersion);

AFX_MODULE_STATE(BOOLbDLL,WNDPROCpfnAfxWndProc,

DWORDdwVersion,BOOLbSystem);

#else

AFX_MODULE_STATE(BOOLbDLL);

#endif

~AFX_MODULE_STATE();

CWinApp*m_pCurrentWinApp;

HINSTANCEm_hCurrentInstanceHandle;

HINSTANCEm_hCurrentResourceHandle;

LPCTSTRm_lpszCurrentAppName;

BYTEm_bDLL;//TRUEifmoduleisaDLL,FALSEifitisanEXE

//TRUEifmoduleisa"system"module,FALSEifnot

BYTEm_bSystem;

BYTEm_bReserved[2];//padding

//Runtimeclassdata:

#ifdef_AFXDLL

CRuntimeClass*m_pClassInit;

#endif

CTypedSimpleListm_classList;

//OLEobjectfactories

#ifndef_AFX_NO_OLE_SUPPORT

#ifdef_AFXDLL

COleObjectFactory*m_pFactoryInit;

#endif

CTypedSimpleListm_factoryList;

#endif

//numberoflockedOLEobjects

longm_nObjectCount;

BOOLm_bUserCtrl;

//AfxRegisterClassandAfxRegisterWndClassdata

TCHARm_szUnregisterList[4096];

#ifdef_AFXDLL

WNDPROCm_pfnAfxWndProc;

DWORDm_dwVersion;//versionthatmodulelinkedagainst

#endif

//variablesrelatedtoagivenprocessinamodule

//(usedtobeAFX_MODULE_PROCESS_STATE)

#ifdef_AFX_OLD_EXCEPTIONS

//exceptions

AFX_TERM_PROCm_pfnTerminate;

#endif

void(PASCAL*m_pfnFilterToolTipMessage)(MSG*,CWnd*);

#ifdef_AFXDLL

//CDynLinkLibraryobjects(forresourcechain)

CTypedSimpleListm_libraryList;

//specialcaseforMFCxxLOC.DLL(localizedMFCresources)

HINSTANCEm_appLangDLL;

#endif

#ifndef_AFX_NO_OCC_SUPPORT

//OLEcontrolcontainermanager

COccManager*m_pOccManager;

//lockedOLEcontrols

CTypedSimpleListm_lockList;

#endif

#ifndef_AFX_NO_DAO_SUPPORT

_AFX_DAO_STATE*m_pDaoState;

#endif

#ifndef_AFX_NO_OLE_SUPPORT

//Typelibrarycaches

CTypeLibCachem_typeLibCache;

CMapPtrToPtr*m_pTypeLibCacheMap;

#endif

//definethreadlocalportionsofmodulestate

THREAD_LOCAL(AFX_MODULE_THREAD_STATE,m_thread)

};

从上面的定义可以看出,模块状态信息分为如下几类:

模块信息,资源信息,对动态链接到MFCDLL的支持信息,对扩展DLL的支持信息,对DAO的支持信息,对OLE的支持信息,模块-线程状态信息。

模块信息包括实例句柄、资源句柄、应用程序名称、指向应用程序的指针、是否为DLL模块、模块注册的窗口类,等等。

其中,成员变量m_fRegisteredClasses、m_szUnregisterList曾经在讨论MFC的窗口注册时提到过它们的用处。

在“#ifdef_AFXDLL…#endif”条件编译范围内的是支持MFCDLL的数据;

在“#ifndef_AFX_NO_OLE_SUPPOR…#endif”条件编译范围内的是支持OLE的数据;

在“#ifndef_AFX_NO_OCC_SUPPOR…#endif”条件编译范围内的是支持OLE控件的数据;

在“#ifndef_AFX_NO_DAO_SUPPORT”条件编译范围内的是支持DAO的数据。

THREAD_LOCAL宏定义了线程私有的模块-线程类型的变量m_thread。

4._AFX_BASE_MODULE_STATE

该类定义如下:

class_AFX_BASE_MODULE_STATE:

publicAFX_MODULE_STATE

{

public:

#ifdef_AFXDLL

_AFX_BASE_MODULE_STATE():

AFX_MODULE_STATE(TRUE,

AfxWndProcBase,_MFC_VER)

#else

_AFX_BASE_MODULE_STATE():

AFX_MODULE_STATE(TRUE)

#endif

{}

};

由定义可见,该类没有在_AFX_MODULE_STATE类的基础上增加数据。

它类用来实现一个MFC应用程序模块的状态信息。

5._AFX_THREAD_STATE

该类定义如下:

class_AFX_THREAD_STATE:

publicCNoTrackObject

{

public:

_AFX_THREAD_STATE();

virtual~_AFX_THREAD_STATE();

//overrideform_pModuleStatein_AFX_APP_STATE

AFX_MODULE_STATE*m_pModuleState;

AFX_MODULE_STATE*m_pPrevModuleState;

//memorysafetypoolfortempmaps

void*m_pSafetyPoolBuffer;//currentbuffer

//threadlocalexceptioncontext

AFX_EXCEPTION_CONTEXTm_exceptionContext;

//CWndcreate,graydialoghook,andotherhookdata

CWnd*m_pWndInit;

CWnd*m_pAlternateWndInit;//specialcasecommdlghooking

DWORDm_dwPropStyle;

DWORDm_dwPropExStyle;

HWNDm_hWndInit;

BOOLm_bDlgCreate;

HHOOKm_hHookOldCbtFilter;

HHOOKm_hHookOldMsgFilter;

//otherCWndmodaldata

MSGm_lastSentMsg;//seeCWnd:

:

WindowProc

HWNDm_hTrackingWindow;//seeCWnd:

:

TrackPopupMenu

HMENUm_hTrackingMenu;

TCHARm_szTempClassName[96];//seeAfxRegisterWndClass

HWNDm_hLockoutNotifyWindow;//seeCWnd:

:

OnCommand

BOOLm_bInMsgFilter;

//otherframeworkmodaldata

CView*m_pRoutingView;//seeCCmdTarget:

:

GetRoutingView

CFrameWnd*m_pRoutingFrame;//seeCmdTarget:

:

GetRoutingFrame

//MFC/DBthread-localdata

BOOLm_bWaitForDataSource;

//commoncontrolsthreadstate

CToolTipCtrl*m_pToolTip;

CWnd*m_pLastHit;//lastwindowtoowntooltip

intm_nLastHit;//lasthittestcode

TOOLINFOm_lastInfo;//lastTOOLINFOstructure

intm_nLastStatus;//lastflybystatusmessage

CControlBar*m_pLastStatus;//lastflybystatuscontrolbar

//OLEcontrolthread-localdata

CWnd*m_pWndPark;//"parkingspace"window

longm_nCtrlRef;//referencecountonparkingwindow

BOOLm_bNeedTerm;//TRUEifOleUninitializeneedstobecalled

};

从定义可以看出,线程状态的成员数据分如下几类:

指向模块状态信息的指针,支持本线程的窗口创建的变量,MFC命令和消息处理用到的信息,处理工具条提示信息(tooltip)的结构,和处理OLE相关的变量,等等。

6.AFX_MODULE_THREAD_STATE

该类定义如下:

//AFX_MODULE_THREAD_STATE(localtothread*and*module)

classAFX_MODULE_THREAD_STATE:

publicCNoTrackObject

{

public:

AFX_MODULE_THREAD_STATE();

virtual~AFX_MODULE_THREAD_STATE();

//currentCWinThreadpointer

CWinThread*m_pCurrentWinThread;

//listofCFrameWndobjectsforthread

CTypedSimpleListm_frameList;

//temporary/permanentmapstate

DWORDm_nTempMapLock;//ifnot0,tempmapslocked

CHandleMap*m_pmapHWND;

CHandleMap*m_pmapHMENU;

CHandleMap*m_pmapHDC;

CHandleMap*m_pmapHGDIOBJ;

CHandleMap*m_pmapHimageLIST;

//thread-localMFCnewhandler(separatefromC-runtime)

_PNHm_pfnNewHandler;

#ifndef_AFX_NO_SOCKET_SUPPORT

//WinSockspecificthreadstate

HWNDm_hSocketWindow;

CMapPtrToPtrm_mapSocketHandle;

CMapPtrToPtrm_mapDeadSockets;

CPtrListm_listSocketNotifications;

#endif

};

模块-线程状态的数据成员主要有:

指向当前线程对象(CWinThread对象)的指针m_pCurrentWinThread;

当前线程的框架窗口对象(CFrameWnd对象)列表m_frameList(边框窗口在创建时(见图5-8)把自身添加到m-frameList中,销毁时则删除掉,通过列表m_frameList可以遍历模块所有的边框窗口);

new操作的例外处理函数m_pfnNewHandler;

临时映射锁定标识m_nTempMapLock,防止并发修改临时映射。

系列Windows对象-MFC对象的映射,如m_pmapHWND等。

这些数据成员都是线程和模块私有的。

下一节讨论MFC如何通过上述这些类来实现其状态的管理。

3.线程局部存储机制和状态的实现

MFC实现线程、模块或者线程-模块私有状态的基础是MFC的线程局部存储机制。

MFC定义了CThreadSlotData类型的全局变量_afxThreadData来为进程的线程分配线程局部存储空间:

CThreadSlotData*_afxThreadData;

在此基础上,MFC定义了变量_afxThreadState来管理线程状态,定义了变量_afxBaseModuleState来管理进程状态。

THREAD_LOCAL(_AFX_THREAD_STATE,_afxThreadState)

PROCESS_LOCAL(_AFX_BASE_MODULE_STATE,_afxBaseModuleState)

对于每个THREAD_LOCAL宏定义的变量,进程的每个线程都有自己独立的拷贝,这个变量在不同的线程里头可以有不同的取值。

对于每个PROCESS_LOCAL宏定义的变量,每个进程都有自己独立的拷贝,这个变量在不同的进程里头可以有不同的取值。

分别解释这三个变量。

1.CThreadSlotData和_afxThreadData

1.CThreadSlotData的定义

以Win32线程局部存储机制为基础,MFC设计了类CThreadSlotData来提供管理线程局部存储的功能,MFC应用程序使用该类的对象──全局变量_afxThreadData来管理本进程的线程局部存储。

CThreadSlotData类的定义如下:

classCThreadSlotData

{

public:

CThreadSlotData();

//Operations

intAllocSlot();

voidFreeSlot(intnSlot);

void*GetValue(intnSlot);

voidSetValue(intnSlot,void*pValue);

//deleteallvaluesinprocess/thread

voidDeleteValues(HINSTANCEhInst,BOOLbAll=FALSE);

//assigninstancehandletojustconstructedslots

voidAssignInstance(HINSTANCEhInst);

//Implementation

DWORDm_tlsIndex;//usedtoaccesssystemthread-localstorage

intm_nAlloc;//numberofslotsallocated(inUINTs)

intm_nRover;//(optimization)forquickfindingoffreeslots

intm_nMax;//sizeofslottablebelow(inbits)

CSlotData*m_pSlotData;//stateofeachslot(allocatedornot)

//listofCThreadDatastructures

CTypedSimpleListm_list;

CRITICAL_SECTIONm_sect;

//specialversionforthreadsonly!

void*GetThreadValue(intnSlot);

void*PASCALoperatornew(size_t,void*p){returnp;}

voidDeleteValues(CThreadData*pData,HINSTANCEhInst);

~CThreadSlotData();

};

通过TLS索引m_tlsIndex,CThreadSlotData对象(_afxThreadData)为每一个线程分配一个线程私有的存储空间并管理该空间。

它把这个空间划分为若干个槽,每个槽放一个线程私有的数据指针,这样每个线程就可以存放任意个线程私有的数据指针。

2.CThreadSlotData的一些数据成员

在CThreadSlotData类的定义中所涉及的类或者结构定义如下:

(1)m_sect

m_sect是一个关键段变量,在_afxThreadData创建时初始化。

因为_afxThreadData是一个全局变量,所以必须通过m_sect来同步多个线程对该变量的并发访问。

(2)m_nAlloc和m_pSlotData

m_nAlloc表示已经分配槽的数目,它代表了线程局部变量的个数。

每一个线程局部变量都对应一个槽,每个槽对应一个线程局部变量。

槽使用CSlotData类来管理。

CSlotData的定义如下:

structCSlotData{

DWORDdwFlags;//slotflags(allocated/notallocated)

HINSTANCEhInst;//modulewhichownsthisslot

};

该结构用来描述槽的使用:

域dwFlags表示槽的状态,即被占用或者没有;

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2