2025-04-27 07:49:33 -04:00

561 lines
8.2 KiB
C++

/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
Abstract:
Author:
Savas Guven (savasg) 27-Nov-2000
Revision History:
--*/
#include "stdafx.h"
//
// Initialize STATIC MEMBERS
//
const PCHAR _GENERIC_NODE::ObjectNamep = "GENERIC_NODE";
const PCHAR _CLIST::ObjectNamep = "CLIST";
_GENERIC_NODE::_GENERIC_NODE()
:Nextp(NULL),
Prevp(NULL),
iKey1(0),
iKey2(0)
{
ICQ_TRC(TM_LIST, TL_DUMP, (" GENERIC_NODE - Default Constructor"));
}
LONG
_GENERIC_NODE::CompareToMe(PGENERIC_NODE Nodep)
{
LONG KeyOne = 0;
LONG KeyTwo = 0;
if(NULL is Nodep) return -1;
if(Nodep->iKey1 is 0 && Nodep->iKey2 is 0) return 0;
if(iKey1 > Nodep->iKey1)
{
KeyOne = 1;
}
else
{
(iKey1 < Nodep->iKey1)?(KeyOne = -1):(KeyOne = 0);
}
if(this->iKey2 is 0 || Nodep->iKey2 is 0)
{
return KeyOne;
}
if(iKey2 > Nodep->iKey2)
{
KeyTwo = 1;
}
else
{
(iKey2 < Nodep->iKey2)?(KeyTwo = -1):(KeyTwo = 0);
}
if (KeyOne < 0) return -1;
if(KeyOne is 0)
{
if(KeyTwo < 0)
return -1;
else if(KeyTwo > 0)
return 1;
}
if (KeyOne > 0) return 1;
// this is the case of KeyOne == 0 and KeyTwo == 0
return 0;
}
//
//
//
_CLIST::_CLIST()
:listHeadp(NULL),
listTailp(NULL)
{
ICQ_TRC(TM_LIST, TL_DUMP, ("CLIST - DEFAULT CONSTRUCTOR"));
}
//
//
//
_CLIST::~_CLIST()
{
ICQ_TRC(TM_LIST, TL_DUMP, ("CLIST - DESTRUCTOR"));
if(this->bCleanupCalled is FALSE)
{
_CLIST::ComponentCleanUpRoutine();
}
this->bCleanupCalled = FALSE;
}
//
// This function is inherited from the COMPONENT_REFERENCE
// Upon Deletion of this List.. it should dereference all the
// elements still within the List.
//
void
_CLIST::ComponentCleanUpRoutine(void)
{
ICQ_TRC(TM_LIST, TL_DUMP, ("CLIST - ComponentCleanUpRoutine"));
FreeExistingNodes();
this->bCleanupCalled = TRUE;
}
BOOLEAN
_CLIST::isListEmpty(VOID)
{
return (listHeadp is NULL);
}
//
// Remove the Head from the List and return - PRIVATE FUNC
//
PGENERIC_NODE
_CLIST::RemoveHead(VOID)
{
PGENERIC_NODE Nodep = NULL;
//Acquire the Lock
// this->AcquireLock();
do
{
if(!isListEmpty())
{
Nodep = listHeadp;
listHeadp = listHeadp->Nextp;
if(listHeadp != NULL)
{
listHeadp->Prevp = NULL;
}
break;
}
} while (FALSE);
// Release the Lock
// this->ReleaseLock();
if(Nodep != NULL)
{
CLEAN_NODE(Nodep);
}
return Nodep;
}
//
// Remove the Last Element of the List. - PRIVATE FUNC
//
PGENERIC_NODE
_CLIST::RemoveTail(VOID)
{
PGENERIC_NODE Nodep = NULL;
// this->AcquireLock();
do
{
if(!isListEmpty())
{
Nodep = listTailp;
listTailp = listTailp->Prevp;
if(listTailp != NULL)
{
listTailp->Nextp = NULL;
}
else if(Nodep is listHeadp)
{
listHeadp = listTailp;
}
break;
}
} while (FALSE);
// this->ReleaseLock();
if(Nodep != NULL)
{
CLEAN_NODE(Nodep);
}
return Nodep;
}
//
// Inserts node into the tail without looking at the keys. - PRIVATE - FUNC
//
VOID
_CLIST::InsertTail(PGENERIC_NODE Nodep)
{
// this->AcquireLock();
do
{
if(listTailp is NULL)
{
listHeadp = listTailp = Nodep;
Nodep->Nextp = NULL;
Nodep->Prevp = NULL;
break;
}
Nodep->Prevp = listTailp;
listTailp->Nextp = Nodep;
listTailp = Nodep;
} while (FALSE);
// this->ReleaseLock();
}
//
// Inserts a node in to the head without looking at the keys. - PRIVATE FUNC
//
VOID
_CLIST::InsertHead(PGENERIC_NODE Nodep)
{
// this->AcquireLock();
do
{
if(listHeadp is NULL)
{
listHeadp = listTailp = Nodep;
Nodep->Prevp = NULL;
Nodep->Nextp = NULL;
break;
}
Nodep->Nextp = listHeadp;
listHeadp->Prevp = Nodep;
listHeadp = Nodep;
} while (FALSE);
// this->ReleaseLock();
}
//
// Inserts the Node as sorted. - PUBLIC
//
VOID
_CLIST::InsertSorted(
PGENERIC_NODE Nodep
)
{
PGENERIC_NODE NodePivotp = NULL;
this->AcquireLock();
do
{
if(!isListEmpty())
{
for(NodePivotp = listHeadp;
NodePivotp != NULL;
NodePivotp = NodePivotp->Nextp)
{
if(NodePivotp->CompareToMe(Nodep) <= 0)
{
break;
}
}
}
else // No elements just bang it in.
{
listHeadp = listTailp = Nodep;
break;
}
// then insert here.
if(NodePivotp is listHeadp)
{
this->InsertHead(Nodep);
}
else if (NodePivotp is NULL)
{
this->InsertTail(Nodep);
}
else // add prior to Pivot
{
Nodep->Prevp = NodePivotp->Prevp;
Nodep->Nextp = NodePivotp;
NodePivotp->Prevp = Nodep;
}
} while(FALSE);
REF_COMPONENT( Nodep, eRefList );
this->ReleaseLock();
}
//
// Search a Node with the Given Keys.
// if there is no such node then return NULL - PUBLIC
//
PGENERIC_NODE
_CLIST::SearchNodeKeys
(
ULONG iKey1,
ULONG iKey2
)
{
GENERIC_NODE TempNode;
PGENERIC_NODE NodePivotp = NULL;
TempNode.iKey1 = iKey1;
TempNode.iKey2 = iKey2;
this->AcquireLock();
if(!isListEmpty())
{
for(NodePivotp = listHeadp;
NodePivotp != NULL;
NodePivotp = NodePivotp->Nextp)
{
if(NodePivotp->CompareToMe(&TempNode) is 0)
{
this->ReleaseLock();
return NodePivotp;
}
}
}
this->ReleaseLock();
return NULL;
}
//
// Remove the node with the given Keys from the List.
//
// Note that SearchKey acquires and releases the Lock once
// we should never Acquire Lock s around functions which holds and
// releases them.
// this will cause the release of the lock two times which is a wrong
// operation - PUBLIC
//
PGENERIC_NODE
_CLIST::RemoveSortedKeys
(
ULONG iKey1,
ULONG iKey2
)
{
PGENERIC_NODE GNp = SearchNodeKeys(iKey1, iKey2);
PGENERIC_NODE EX_Prevp = NULL;
PGENERIC_NODE EX_Nextp = NULL;
this->AcquireLock();
do
{
if(GNp != NULL)
{
if(GNp is listHeadp)
{
RemoveHead();
}
else if(GNp is listTailp)
{
RemoveTail();
}
else if(!isListEmpty())
{
EX_Prevp = GNp->Prevp;
EX_Nextp = GNp->Nextp;
// ASSERT(EX_Prevp);
EX_Prevp->Nextp = EX_Nextp;
// ASSERT(EX_Nextp);
EX_Nextp->Prevp = EX_Prevp;
}
CLEAN_NODE( GNp );
STOP_COMPONENT( GNp );
DEREF_COMPONENT( GNp, eRefList );
}
} while(FALSE);
this->ReleaseLock();
return GNp;
}
//
// PUBLIC
//
PGENERIC_NODE
_CLIST::RemoveNodeFromList(PGENERIC_NODE Pivotp)
{
PGENERIC_NODE Nodep = NULL, EX_Prevp = NULL, EX_Nextp = NULL;
if(Pivotp is NULL) return NULL;
this->AcquireLock();
do
{
for(Nodep = listHeadp;
Nodep != NULL;
Nodep = Nodep->Nextp)
{
if(Nodep is Pivotp)
{
if(Nodep is listHeadp)
{
RemoveHead();
}
else if(Nodep is listTailp)
{
RemoveTail();
}
else if(!isListEmpty())
{
EX_Prevp = Nodep->Prevp;
EX_Nextp = Nodep->Nextp;
// ASSERT(EX_Prevp);
EX_Prevp->Nextp = EX_Nextp;
// ASSERT(EX_Nextp);
EX_Nextp->Prevp = EX_Prevp;
}
CLEAN_NODE( Nodep );
STOP_COMPONENT( Nodep );
DEREF_COMPONENT( Nodep, eRefList );
break;
}
}
} while (FALSE);
this->ReleaseLock();
return Nodep;
}
//
// POP is as the stack operation POP would be.. it returns the HEAD of the List
// PUBLIC FUNCTION
//
PGENERIC_NODE
_CLIST::Pop()
{
PGENERIC_NODE Nodep = NULL;
this->AcquireLock();
Nodep = this->RemoveHead();
if(Nodep != NULL)
{
DEREF_COMPONENT( Nodep, eRefList );
}
this->ReleaseLock();
return Nodep;
}
//
// PRIVATE FUNC
//
VOID
_CLIST::FreeExistingNodes()
{
PGENERIC_NODE Nodep;
ICQ_TRC(TM_LIST, TL_TRACE, ("CLIST - FreeExistingNodes "));
for(Nodep = listHeadp;
Nodep != NULL;
Nodep = listHeadp)
{
// take Nodep out of List.
listHeadp = Nodep->Nextp;
if(listHeadp != NULL)
{
listHeadp->Prevp = Nodep->Prevp;
}
CLEAN_NODE(Nodep);
STOP_COMPONENT(Nodep);
DEREF_COMPONENT( Nodep, eRefList);
}
listHeadp = NULL;
listTailp = NULL;
}