588 lines
9.7 KiB
C++
588 lines
9.7 KiB
C++
/*++
|
|
|
|
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;
|
|
}
|