#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 #include /****************************************************************************** * * 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