windows-nt/Source/XPSP1/NT/shell/ext/ratings/common/npcrit.cpp
2020-09-26 16:20:57 +08:00

181 lines
4 KiB
C++

/*****************************************************************/
/** Microsoft Windows for Workgroups **/
/** Copyright (C) Microsoft Corp., 1993-1994 **/
/*****************************************************************/
/* npcrit.c -- Implementation of critical section classes.
*
* History:
* 11/01/93 gregj Created
*/
#include "npcommon.h"
#include <npcrit.h>
#include <npassert.h>
/*
* Very simple interlock routines, used to stop race conditions when
* initializing and de-initializing critical sections. Do NOT use
* these for anything other than infrequent extremely short-term locks,
* since WaitForInterlock contains a spin loop with a millisecond delay!
*/
BYTE InterlockedSet(volatile BYTE *pByte)
{
BYTE bRet;
_asm {
mov edi, pByte
mov al, 1
xchg [edi], al /* store non-zero value, get what was there before */
mov bRet, al
}
return bRet;
}
void WaitForInterlock(volatile BYTE *pByte)
{
for (;;) {
BYTE bAlreadyOwned = InterlockedSet(pByte); /* attempt to grab the interlock */
if (!bAlreadyOwned) /* is someone else in there? */
break; /* nope, we now own it */
Sleep(1); /* yield to whomever owns it, then try again */
}
}
void ReleaseInterlock(volatile BYTE *pByte)
{
*pByte = 0; /* clear the interlock to release others */
}
#if 0
// Remove CRITSEC code but keep for a while before deleting.
/*******************************************************************
NAME: CRITSEC::Init
SYNOPSIS: Initializes a global critical section object
ENTRY: pszName - name for the critical section
EXIT: No return value
NOTES: Currently pszName is not used; it will be used
for named mutexes later.
HISTORY:
gregj 11/01/93 Created
********************************************************************/
void CRITSEC::Init(char *pszName)
{
WaitForInterlock(&_bInterlock);
if (!_fInitialized) {
::InitializeCriticalSection(&_critsec);
#ifdef DEBUG
_wClaimCount = 0;
#endif
_fInitialized = 1;
}
ReleaseInterlock(&_bInterlock);
_cClients++;
}
/*******************************************************************
NAME: CRITSEC::Term
SYNOPSIS: Cleans up resources allocated for a critical section
ENTRY: No parameters
EXIT: No return value
NOTES: This function should be callled at process attach.
It will take care of making sure it only deletes
the critical section when the last process using
it calls Term().
HISTORY:
gregj 11/01/93 Created
********************************************************************/
void CRITSEC::Term()
{
WaitForInterlock(&_bInterlock);
BOOL fShouldCleanUp = (--_cClients == 0);
if (fShouldCleanUp) {
::DeleteCriticalSection(&_critsec);
_fInitialized = 0;
}
ReleaseInterlock(&_bInterlock);
}
#ifdef DEBUG /* in retail, these are inline */
/*******************************************************************
NAME: CRITSEC::Enter
SYNOPSIS: Enters a critical section
ENTRY: No parameters
EXIT: No return value; critical section is owned by
the calling thread
NOTES: This function is private, and is invoked indirectly
by the friend class TAKE_CRITSEC.
HISTORY:
gregj 11/01/93 Created
********************************************************************/
void CRITSEC::Enter()
{
#ifdef DEBUG
UIASSERT(_fInitialized != 0);
#endif
::EnterCriticalSection(&_critsec);
#ifdef DEBUG
_wClaimCount++;
#endif
}
/*******************************************************************
NAME: CRITSEC::Leave
SYNOPSIS: Leaves a critical section
ENTRY: No parameters
EXIT: No return value; critical section is released
NOTES: This function is private, and is invoked indirectly
by the friend class TAKE_CRITSEC.
HISTORY:
gregj 11/01/93 Created
********************************************************************/
void CRITSEC::Leave()
{
#ifdef DEBUG
UIASSERT(_fInitialized != 0);
UIASSERT(_wClaimCount > 0);
_wClaimCount--;
#endif
::LeaveCriticalSection(&_critsec);
}
#endif /* DEBUG */
#endif /* 0 */