Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

587 lines
9.7 KiB

/*++
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;
}