|
|
/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
Abstract:
Author:
Savas Guven (savasg) 27-Nov-2000
Revision History:
--*/ #include "stdafx.h"
//#include "sync.h"
#define ERROR_CREATING_SYNC_OBJECT 0x0001
//
// STATIC MEMBER INITIALIZATIONS
//
const PCHAR COMPONENT_SYNC::ObjectNamep = "COMPONENT_SYNC";
COMPONENT_SYNC::COMPONENT_SYNC() /*++
Routine Description:
Deafault Constructor Arguments:
NONE
Return Value:
NONE
--*/ :Deleted(FALSE), bCleanupCalled(FALSE), m_ReferenceCount(1) { ICQ_TRC(TM_SYNC, TL_DUMP, ("%s> COMPONENT::DeFAULT Constructor", this->GetObjectName()));
this->InitializeSync(); }
COMPONENT_SYNC::~COMPONENT_SYNC() /*++
Routine Description:
Destructor of the COMPONEN_REFERENCE and SYNC object Arguments:
NONE
Return Value:
NONE
--*/ { ICQ_TRC(TM_SYNC, TL_DUMP, ("%s> COMPONENT::~ Destructor", this->GetObjectName()));
if(this->bCleanupCalled is FALSE) { COMPONENT_SYNC::ComponentCleanUpRoutine(); }
this->bCleanupCalled = FALSE; }
void COMPONENT_SYNC::ComponentCleanUpRoutine(void) /*++
Routine Description:
CleanupRoutine of the SYNCHRONIZATION Object. Only the CRITICAL_SECTION needs to be deleted properly. Arguments:
NONE
Return Value:
NONE
--*/ { ICQ_TRC(TM_SYNC, TL_TRACE, ("%s> COMPONENT::ComponentCleanUpRoutine", this->GetObjectName()));
DeleteSync();
this->bCleanupCalled = TRUE; }
void COMPONENT_SYNC::DeleteSync( void ) /*++
Routine Description:
This routine is called to destroy a component reference. It may only be called after the lastreference to the component is released, i.e. after 'ReleaseComponentReference' has returned 'TRUE'. It may also be called from within the component's 'CleanupRoutine'.
Arguments:
ComponentReference - the component to be destroyed
Return Value:
none.
--*/ { DeleteCriticalSection(&this->m_Lock);
#if COMPREF_DEBUG_TRACKING
if ( m_RecordArray != NULL ) HeapFree(GetProcessHeap(), 0, m_RecordArray);
m_RecordArray = NULL;
#endif
}
ULONG COMPONENT_SYNC::InitializeSync(void) /*++
Routine Description:
This routine is called to initialize a component reference.
Arguments:
ComponentReference - the component to be initialized
CleanupRoutine - the routine to be called when the component is to be cleaned up (within the final 'ReleaseComponentReference').
Return Value:
none.
--*/ { ICQ_TRC(TM_SYNC, TL_DUMP, ("COMPONENT - InitializeSync"));
InitializeCriticalSection(&this->m_Lock);
this->Deleted = FALSE; this->bCleanupCalled = FALSE; this->m_ReferenceCount = 1;
#if COMPREF_DEBUG_TRACKING
m_RecordIndex = 0; m_RecordArray = (PCOMPREF_DEBUG_RECORD_)HeapAlloc(GetProcessHeap(), 0, sizeof(COMPREF_DEBUG_RECORD_) * _COMPREF_DEBUG_RECORD_COUNT );
if ( m_RecordArray != NULL ) { ZeroMemory(m_RecordArray, sizeof(COMPREF_DEBUG_RECORD_) * _COMPREF_DEBUG_RECORD_COUNT); }
#endif
return NO_ERROR; }
BOOLEAN COMPONENT_SYNC::ReferenceSync(void) /*++
Routine Description:
This routine is called to increment the reference-count to a component. The attempt may fail if the initial reference has been released and the component is therefore being deleted.
Arguments:
ComponentReference - the component to be referenced
Return Value:
BOOLEAN - TRUE if the component was referenced, FALSE otherwise.
--*/ { ICQ_TRC(TM_SYNC, TL_TRACE, ("%s> COMPONENT - REFERENCE %u + 1", this->GetObjectName(), this->m_ReferenceCount));
EnterCriticalSection(&this->m_Lock);
if(this->Deleted) { LeaveCriticalSection(&this->m_Lock);
return FALSE; }
InterlockedIncrement( (LPLONG) &m_ReferenceCount) ;
LeaveCriticalSection(&this->m_Lock);
return TRUE; }
BOOLEAN COMPONENT_SYNC::DereferenceSync( void ) /*++
Routine Description:
This routine is called to drop a reference to a component. If the reference drops to zero, cleanup is performed. Otherwise, cleanup occurs later when the last reference is released.
Arguments:
ComponentReference - the component to be referenced
Return Value:
BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
--*/ { ICQ_TRC(TM_SYNC, TL_TRACE, ("%s> DEREFERENCE %u - 1", this->GetObjectName(), this->m_ReferenceCount));
this->AcquireLock();
if( InterlockedDecrement((LPLONG) &m_ReferenceCount) ) { this->ReleaseLock();
return FALSE; }
this->ReleaseLock();
this->ComponentCleanUpRoutine();
this->Deleted = TRUE;
return TRUE; }
//
//
//
inline void COMPONENT_SYNC::AcquireLock() { ICQ_TRC(TM_SYNC, TL_DUMP, ("COMPONENT - Acquire Lock"));
EnterCriticalSection(&m_Lock); }
inline void COMPONENT_SYNC::ReleaseLock() { ICQ_TRC(TM_SYNC, TL_DUMP, ("COMPONENT - Release Lock"));
LeaveCriticalSection(&m_Lock); }
#if 0
void COMPONENT_SYNC::ResetSync(void) /*++
Routine Description:
This routine is called to reset a component reference to an initial state.
Arguments:
ComponentReference - the component to be reset
Return Value:
none.
--*/ { EnterCriticalSection(&this->m_Lock);
this->m_ReferenceCount = 1; this->Deleted = FALSE;
#if COMPREF_DEBUG_TRACKING
this->RecordIndex = 0;
ZeroMemory(this->RecordArray, sizeof(COMPREF_DEBUG_RECORD_) * _COMPREF_DEBUG_RECORD_COUNT);
#endif
} // Release
BOOLEAN COMPONENT_SYNC::ReleaseInitialSync(void) /*++
Routine Description:
This routine is called to drop the initial reference to a component, and mark the component as deleted. If the reference drops to zero, cleanup is performed right away.
Arguments:
ComponentReference - the component to be referenced
Return Value:
BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
--*/ { this->AcquireLock();
if(this->Deleted) { this->ReleaseLock();
return TRUE; }
this->Deleted = TRUE;
if(--this->m_ReferenceCount) { this->ReleaseLock();
return FALSE; }
this->ReleaseLock();
this->ComponentCleanUpRoutine();
return TRUE; }
#endif
BOOLEAN COMPONENT_SYNC::RecordRef( ULONG RefId, PCHAR File, ULONG Line ) /*++
Routine Description:
Arguments:
FILE - Records in which file the SYNC object is accessed LINE - which Line in the FILE TYPE - and the TYPE of operation desired
Return Value:
none.
--*/
{
#if COMPREF_DEBUG_TRACKING
if ( NULL == m_RecordArray ) { return FALSE; }
this->AcquireLock();
//
// Find The first empty slot to which to add this.
//
for ( int i = 0; i < _COMPREF_DEBUG_RECORD_COUNT; i++ ) { if ( FALSE == m_RecordArray[i].bInUse ) { m_RecordArray[i].OpCode = RefId;
m_RecordArray[i].File = File;
m_RecordArray[i].Line = Line;
m_RecordArray[i].Type = eReferencing;
m_RecordArray[i].bInUse = TRUE;
break; } }
this->ReleaseLock();
#endif
return TRUE; }
BOOLEAN COMPONENT_SYNC::RecordDeref( ULONG RefId, PCHAR File, ULONG Line ) { int UnusedEntryIndex = -1;
BOOLEAN bFound = FALSE;
#if COMPREF_DEBUG_TRACKING
if ( NULL == m_RecordArray ) { return FALSE; } this->AcquireLock(); //
// Search for the RefId in the existing
//
for ( int i = 0; i < _COMPREF_DEBUG_RECORD_COUNT; i++ ) { //
// if you find a reference with the same OpCode / RefId delete the entry
//
if ( ( TRUE == m_RecordArray[i].bInUse ) && ( m_RecordArray[i].OpCode == RefId ) ) { ZeroMemory( &(m_RecordArray[i]), sizeof(COMPREF_DEBUG_RECORD_) );
bFound = TRUE;
break; }
if ( (-1 == UnusedEntryIndex ) && (FALSE == m_RecordArray[i].bInUse) ) { UnusedEntryIndex = i; } }
//
// if there is no REF code for this DEREF note it down
//
if ( (FALSE == bFound) && (0 <= UnusedEntryIndex) ) { m_RecordArray[i].OpCode = RefId;
m_RecordArray[i].File = File;
m_RecordArray[i].Line = Line;
m_RecordArray[i].Type = eDereferencing;
m_RecordArray[i].bInUse = TRUE; }
this->ReleaseLock();
#endif
return TRUE; }
BOOLEAN COMPONENT_SYNC::ReportRefRecord() {
#if COMPREF_DEBUG_TRACKING
if ( NULL == m_RecordArray ) { return FALSE; }
//
// scan the Ref Records and print them..
//
ICQ_TRC(TM_SYNC, TL_ERROR, ("Object Name: %s Ref History :", this->GetObjectName()));
for (int i = 0; i < _COMPREF_DEBUG_RECORD_COUNT; i++) { if ( TRUE == m_RecordArray[i].bInUse ) { ICQ_TRC(TM_SYNC, TL_ERROR, ("%d) OpCode (%X), File (%s), Line (%u), Type (%s)", i, m_RecordArray[i].OpCode, m_RecordArray[i].File, m_RecordArray[i].Line, (eReferencing == m_RecordArray[i].Type)?"Ref":"Deref")); } } #endif
return TRUE; }
|