windows下轻量级互斥锁

typedef class mutex_lock
{
public:
 mutex_lock()
  : LockCount(-1)
  , hEvent(0)
 {
 }
 ~mutex_lock()
 {
  if(NULL != this->hEvent)
  {
   CloseHandle(this->hEvent);
  }
  this->hEvent = NULL;
  this->LockCount = -1;
 }
 long GetLock();
 long ReleaseLock();
private:
 mutex_lock(mutex_lock&);
 long LockCount;
 HANDLE hEvent;
} MUTEXLOCK, *LPMUTEXLOCK;

long mutex_lock::GetLock()
{
 __asm
 {
   mov  ebx, [this];    // 把基址保存在ebx中
 lock inc  dword ptr [ebx];   // 对LockCount进行加锁加,保证多CPU时的唯一性,
   je  LRET1;      // 如果LockCount加1为0的话,表示没有人在使用资源,同时利用上面的互斥加对资源进行占用。
   cmp  dword ptr [ebx+4], 0;  // 此时LockCount加1大于0的情况,表示已有人使用此资源,要对此资源进行加内核锁
   jne  L1;       // 如果平常没有创建内核锁,则进行创始一个
   push 0;
   push 0;
   push 0;
   push 0;
   call dword ptr [CreateEvent];
   mov  edx, eax;    // 创建内存锁成功后,在同样对hEvent变量进行互斥比较后替换,以处理多个线程同时对此值进行替换的情况,保证只有一个能够成功替换
   mov  eax, 0;
 lock cmpxchg dword ptr [ebx+4], edx; // 互斥比较替换
   je  L1;
   push edx;      // 如果已经被别人替换过了,需要把自己创建的内核锁释放
   call dword ptr [CloseHandle];
L1:
   push INFINITE;     
   push [ebx+4];
   call dword ptr [WaitForSingleObject]; // 在内核级进行等待
LRET1:
   mov  eax, 0
 }
}

long mutex_lock::ReleaseLock()
{
 __asm
 {
   mov  ebx, [this];    // 把基址保存在ebx中
   mov  eax, -1;     
 lock xadd dword ptr [ebx], eax; // 进行交换自减交换操作,运行后,eax中是第一操作数先前的值,此值用会返回用来判断是否多调用了ReleaseLock
   jl  LRET2;      // 没有别的线程占用资源,直接返回,用户可以通过返回值,分析是否失败
   cmp  dword ptr [ebx+4], 0;  // 有别的线程在等待,检查内核锁,如果没有则进行创建
   jne  L2;
   push 0;
   push 0;
   push 0;
   push 0;
   call dword ptr [CreateEvent];
   mov  edx, eax;
   mov  eax, 0;
 lock cmpxchg dword ptr [ebx+4], edx; // 互斥替换内核锁句柄
   je  L2;       // 已经有内核锁了,把自已申请的关闭
   push edx;
   call dword ptr [CloseHandle];

L2:
   push [ebx+4];     // 设计信号,唤醒一个线程
   call dword ptr [SetEvent];
   mov  eax, 0;
LRET2:
 }
}

你可能感兴趣的:(windows下轻量级互斥锁)