windows-nt/Source/XPSP1/NT/admin/wmi/wbem/common/containers/readerwriter.cpp
2020-09-26 16:20:57 +08:00

485 lines
10 KiB
C++

#ifndef __READERWRITER_CPP
#define __READERWRITER_CPP
/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
ReaderWriter.cpp
Abstract:
Enhancements to current functionality:
Timeout mechanism should track across waits.
AddRef/Release on task when scheduling.
Enhancement Ticker logic.
History:
--*/
#include <windows.h>
#include <ReaderWriter.h>
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiMultiReaderSingleWriter :: WmiMultiReaderSingleWriter (
const LONG &a_ReaderSize
) : m_ReaderSize ( a_ReaderSize ) ,
m_ReaderSemaphore ( NULL ) ,
m_InitializationStatusCode ( e_StatusCode_Success ) ,
m_WriterCriticalSection (NOTHROW_LOCK)
{
m_InitializationStatusCode = WmiHelper :: InitializeCriticalSection ( & m_WriterCriticalSection ) ;
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_ReaderSemaphore = CreateSemaphore ( NULL , m_ReaderSize , m_ReaderSize , NULL ) ;
if ( ! m_ReaderSemaphore )
{
m_InitializationStatusCode = e_StatusCode_OutOfResources ;
}
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiMultiReaderSingleWriter :: ~WmiMultiReaderSingleWriter ()
{
WmiHelper :: DeleteCriticalSection ( & m_WriterCriticalSection ) ;
if ( m_ReaderSemaphore )
{
CloseHandle ( m_ReaderSemaphore ) ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderSingleWriter :: Initialize ()
{
return m_InitializationStatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderSingleWriter :: UnInitialize ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderSingleWriter :: EnterRead ()
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
WmiStatusCode t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_WriterCriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
LONG t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
if ( t_Reason != WAIT_OBJECT_0 )
{
t_StatusCode = e_StatusCode_Unknown ;
}
WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
}
return t_StatusCode ;
}
return e_StatusCode_NotInitialized ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderSingleWriter :: EnterWrite ()
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
WmiStatusCode t_StatusCode = WmiHelper :: EnterCriticalSection ( & m_WriterCriticalSection ) ;
if ( t_StatusCode == e_StatusCode_Success )
{
bool t_Waiting = true ;
while ( t_Waiting )
{
LONG t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
if ( t_Reason != WAIT_OBJECT_0 )
{
WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
return e_StatusCode_Unknown ;
}
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
if ( t_Status )
{
if ( t_SemaphoreCount == m_ReaderSize - 1 )
{
t_Waiting = false ;
}
else
{
SwitchToThread () ;
}
}
else
{
WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
return e_StatusCode_Unknown ;
}
}
return t_StatusCode ;
}
}
return e_StatusCode_NotInitialized ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderSingleWriter :: LeaveRead ()
{
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
if ( t_Status )
{
return e_StatusCode_Success ;
}
return e_StatusCode_Unknown ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderSingleWriter :: LeaveWrite ()
{
return WmiHelper :: LeaveCriticalSection ( & m_WriterCriticalSection ) ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiMultiReaderMultiWriter :: WmiMultiReaderMultiWriter (
const LONG &a_ReaderSize ,
const LONG &a_WriterSize
) : m_ReaderSize ( a_ReaderSize ) ,
m_ReaderSemaphore ( NULL ) ,
m_WriterSize ( a_WriterSize ) ,
m_WriterSemaphore ( NULL ) ,
m_InitializationStatusCode ( e_StatusCode_Success )
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_ReaderSemaphore = CreateSemaphore ( NULL , m_ReaderSize , m_ReaderSize , NULL ) ;
if ( ! m_ReaderSemaphore )
{
m_InitializationStatusCode = e_StatusCode_OutOfResources ;
}
}
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
m_WriterSemaphore = CreateSemaphore ( NULL , m_WriterSize , m_WriterSize , NULL ) ;
if ( ! m_ReaderSemaphore )
{
m_InitializationStatusCode = e_StatusCode_OutOfResources ;
}
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiMultiReaderMultiWriter :: ~WmiMultiReaderMultiWriter ()
{
if ( m_ReaderSemaphore )
{
CloseHandle ( m_ReaderSemaphore ) ;
}
if ( m_WriterSemaphore )
{
CloseHandle ( m_WriterSemaphore ) ;
}
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderMultiWriter :: Initialize ()
{
return m_InitializationStatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderMultiWriter :: UnInitialize ()
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
return t_StatusCode ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderMultiWriter :: EnterRead ( const LONG &a_Timeout )
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
LONG t_Reason = WaitForSingleObject ( m_WriterSemaphore , INFINITE ) ;
if ( t_Reason != WAIT_OBJECT_0 )
{
return e_StatusCode_Unknown ;
}
t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
if ( t_Reason != WAIT_OBJECT_0 )
{
t_StatusCode = e_StatusCode_Unknown ;
}
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Unknown ;
}
return t_StatusCode ;
}
return e_StatusCode_NotInitialized ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderMultiWriter :: EnterWrite ( const LONG &a_Timeout )
{
if ( m_InitializationStatusCode == e_StatusCode_Success )
{
WmiStatusCode t_StatusCode = e_StatusCode_Success ;
LONG t_Reason = WaitForSingleObject ( m_WriterSemaphore , INFINITE ) ;
if ( t_Reason != WAIT_OBJECT_0 )
{
return e_StatusCode_Unknown ;
}
bool t_Waiting = true ;
while ( t_Waiting )
{
LONG t_Reason = WaitForSingleObject ( m_ReaderSemaphore , INFINITE ) ;
if ( t_Reason != WAIT_OBJECT_0 )
{
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Unknown ;
}
return e_StatusCode_Unknown ;
}
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
if ( t_Status )
{
if ( t_SemaphoreCount == m_ReaderSize - 1 )
{
t_Waiting = false ;
}
else
{
SwitchToThread () ;
}
}
else
{
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
if ( ! t_Status )
{
t_StatusCode = e_StatusCode_Unknown ;
}
return e_StatusCode_Unknown ;
}
}
return t_StatusCode ;
}
return e_StatusCode_NotInitialized ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderMultiWriter :: LeaveRead ()
{
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_ReaderSemaphore , 1 , & t_SemaphoreCount ) ;
if ( t_Status )
{
return e_StatusCode_Success ;
}
return e_StatusCode_Unknown ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
WmiStatusCode WmiMultiReaderMultiWriter :: LeaveWrite ()
{
LONG t_SemaphoreCount = 0 ;
BOOL t_Status = ReleaseSemaphore ( m_WriterSemaphore , 1 , & t_SemaphoreCount ) ;
if ( t_Status )
{
return e_StatusCode_Success ;
}
return e_StatusCode_Unknown ;
}
#endif __READERWRITER_CPP