一、_Lockit类的定义:
vs 2005中有一个_Lockit类,它是为了线程同步而设置的。_Lockit定义如下(代码有删减):
class _Lockit { // lock while object in existence -- MUST NEST public: explicit __thiscall _Lockit(); // set default lock explicit __thiscall _Lockit(int); // set the lock __thiscall ~_Lockit(); // clear the lock static void __cdecl _Lockit_ctor(int); static void __cdecl _Lockit_dtor(int); private: static void __cdecl _Lockit_ctor(_Lockit *); static void __cdecl _Lockit_ctor(_Lockit *, int); static void __cdecl _Lockit_dtor(_Lockit *); _Lockit(const _Lockit&); // not defined _Lockit& operator=(const _Lockit&); // not defined int _Locktype; };
其中,包含一个成员变量_Locktype;该成员变量有四种可能:
// yvals.h #define _LOCK_LOCALE 0 #define _LOCK_MALLOC 1 // 内存申请 #define _LOCK_STREAM 2 // 用于流操作互斥 #define _LOCK_DEBUG 3 // 用于调试
二、实现:
// xlock.cpp 节选部分代码 __thiscall _Lockit::_Lockit(int kind) : _Locktype(kind & (MAX_LOCK - 1)) { // lock the mutex _Mtxlock(&mtx[_Locktype]); } __thiscall _Lockit::~_Lockit() { // unlock the mutex _Mtxunlock(&mtx[_Locktype]); } void __cdecl _Lockit::_Lockit_ctor(_Lockit * _This, int kind) { // lock the mutex _This->_Locktype = kind & (MAX_LOCK - 1); _Mtxlock(&mtx[_This->_Locktype]); } void __cdecl _Lockit::_Lockit_dtor(_Lockit * _This) { // unlock the mutex _Mtxunlock(&mtx[_This->_Locktype]); }
1、mtx是个位于xlock.cpp中的静态变量。
static _Rmtx mtx[MAX_LOCK]; // 锁 static long init = -1; // 已经初始化锁的数量
2、_Lockit的实现主要依赖两个函数 _Mtxlock 和 _Mtxunlock 函数,这两个函数位于xmtx.c中
void __CLRCALL_PURE_OR_CDECL _Mtxlock(_Rmtx *_Mtx) { /* lock mutex */ EnterCriticalSection(_Mtx); } void __CLRCALL_PURE_OR_CDECL _Mtxunlock(_Rmtx *_Mtx) { /* unlock mutex */ LeaveCriticalSection(_Mtx); }
从这里可以看出,这两个函数调用的是EnterCriticalSection 和 LeaveCriticalSection,可见这个锁是依赖临界区来实现的。
但这个函数的参数类型应该是CRITICAL_SECTION的指针,实现中却是_Rmtx*。原来,在xmtx.h中有这么一句:
typedef CRITICAL_SECTION _Rmtx;
三、临界区初始化:
那临界区在使用前是需要初始化的,在哪里有初始化代码呢?
在xlock.cpp中还有一个静态变量:
static _Init_locks initlocks;
正是该静态变量的构造函数初始化了。
_Init_locks的定义:
class _CRTIMP2_PURE _Init_locks { // initialize mutexes public: __thiscall _Init_locks(); __thiscall ~_Init_locks(); }; __thiscall _Init_locks::_Init_locks() { // initialize locks if (InterlockedIncrement(&init) == 0) for (int count = 0; count < MAX_LOCK; ++count) _Mtxinit(&mtx[count]); } __thiscall _Init_locks::~_Init_locks() { // clean up locks if (InterlockedDecrement(&init) < 0) for (int count = 0; count < MAX_LOCK; ++count) _Mtxdst(&mtx[count]); }