You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
4.1 KiB
182 lines
4.1 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
SYNC.CPP
|
|
|
|
Abstract:
|
|
|
|
Synchronization
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "sync.h"
|
|
#include <cominit.h>
|
|
#include <wbemutil.h>
|
|
#include <corex.h>
|
|
|
|
CHaltable::CHaltable() : m_lJustResumed(1), m_dwHaltCount(0), m_csHalt()
|
|
{
|
|
// This event will be signaled whenever we are not halted
|
|
// ======================================================
|
|
|
|
m_hReady = CreateEvent(NULL, TRUE, TRUE, NULL);
|
|
if (NULL == m_hReady) throw CX_MemoryException(); // exception caught in wbemess esssink.cpp
|
|
}
|
|
|
|
CHaltable::~CHaltable()
|
|
{
|
|
CloseHandle(m_hReady);
|
|
}
|
|
|
|
HRESULT CHaltable::Halt()
|
|
{
|
|
CInCritSec ics(&m_csHalt); // in critical section
|
|
|
|
m_dwHaltCount++;
|
|
ResetEvent(m_hReady);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CHaltable::Resume()
|
|
{
|
|
CInCritSec ics(&m_csHalt); // in critical section
|
|
|
|
m_dwHaltCount--;
|
|
if(m_dwHaltCount == 0)
|
|
{
|
|
SetEvent(m_hReady);
|
|
m_lJustResumed = 1;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CHaltable::ResumeAll()
|
|
{
|
|
CInCritSec ics(&m_csHalt); // in critical section
|
|
m_dwHaltCount = 1;
|
|
return Resume();
|
|
}
|
|
|
|
|
|
HRESULT CHaltable::WaitForResumption()
|
|
{
|
|
while (WbemWaitForSingleObject(m_hReady, INFINITE) == WAIT_FAILED)
|
|
Sleep(0);
|
|
if(InterlockedDecrement(&m_lJustResumed) == 0)
|
|
{
|
|
// The first call after resumption
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
// weren't halted
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
|
|
BOOL CHaltable::IsHalted()
|
|
{
|
|
// Approximate!
|
|
return m_dwHaltCount > 0;
|
|
}
|
|
|
|
CWbemCriticalSection::CWbemCriticalSection( void )
|
|
: m_lLock( -1 ), m_lRecursionCount( 0 ), m_dwThreadId( 0 ), m_hEvent( NULL )
|
|
{
|
|
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
|
|
if ( NULL == m_hEvent )
|
|
{
|
|
throw CX_MemoryException();
|
|
}
|
|
}
|
|
|
|
CWbemCriticalSection::~CWbemCriticalSection( void )
|
|
{
|
|
if ( NULL != m_hEvent )
|
|
{
|
|
CloseHandle( m_hEvent );
|
|
m_hEvent = NULL;
|
|
}
|
|
}
|
|
|
|
BOOL CWbemCriticalSection::Enter( DWORD dwTimeout /* = 0xFFFFFFFF */ )
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
|
|
// Only do this once
|
|
DWORD dwCurrentThreadId = GetCurrentThreadId();
|
|
|
|
// Check if we are the current owning thread. We can do this here because
|
|
// this test will ONLY succeed in the case where we have a Nested Lock(),
|
|
// AND because we are zeroing out the thread id when the lock count hits
|
|
// 0.
|
|
|
|
if( dwCurrentThreadId == m_dwThreadId )
|
|
{
|
|
// It's us - Bump the lock count
|
|
// =============================
|
|
|
|
InterlockedIncrement( &m_lRecursionCount );
|
|
return TRUE;
|
|
}
|
|
|
|
// 0 means we got the lock
|
|
if ( 0 == InterlockedIncrement( &m_lLock ) )
|
|
{
|
|
m_dwThreadId = dwCurrentThreadId;
|
|
m_lRecursionCount = 1;
|
|
fReturn = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// We wait. If we got a signalled event, then we now own the
|
|
// critical section. Otherwise, we should perform an InterlockedDecrement
|
|
// to account for the Increment that got us here in the first place.
|
|
if ( WaitForSingleObject( m_hEvent, dwTimeout ) == WAIT_OBJECT_0 )
|
|
{
|
|
m_dwThreadId = dwCurrentThreadId;
|
|
m_lRecursionCount = 1;
|
|
fReturn = TRUE;
|
|
}
|
|
else
|
|
{
|
|
InterlockedDecrement( &m_lLock );
|
|
}
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
void CWbemCriticalSection::Leave( void )
|
|
{
|
|
// We don't check the thread id, so we can lock/unlock resources
|
|
// across multiple threads
|
|
|
|
BOOL fReturn = FALSE;
|
|
|
|
long lRecurse = InterlockedDecrement( &m_lRecursionCount );
|
|
|
|
// The recursion count hit zero, so it's time to unlock the object
|
|
if ( 0 == lRecurse )
|
|
{
|
|
// If the lock count is >= 0, threads are waiting, so we need to
|
|
// signal the event
|
|
|
|
m_dwThreadId = 0;
|
|
if ( InterlockedDecrement( &m_lLock ) >= 0 )
|
|
{
|
|
SetEvent( m_hEvent );
|
|
}
|
|
|
|
} // If recursion count is at 0
|
|
|
|
}
|
|
|