一、_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]);
}