485 lines
10 KiB
C++
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
|