|
|
// Copyright (c) 1997-2002 Microsoft Corporation
//
// Module:
//
// common utility
//
// Abstract:
//
// NT list api wrapper.
//
// The NT list API is a very efficient and robust list API because:
//
// a) all operations are guarenteed to succeed in constant time without
// any branch instructions
//
// b) memory is used in an optimum way since LIST_ENTRY structures
// are embedded into the objects stored in the list. This means
// that the heap does not get fragmented with list nodes. It also
// allows entries to be removed/transferred/moved without ever
// having to free or reallocate a list node.
//
// One drawback to the NT list API is that it comes with a learning curve
// for most people.
//
// This header defines a wrapper of the NT list API to:
//
// - Allow for easy instrumentation. Modules that use this API can be
// specially purposed to store state with the lists, nodes, etc.
//
// - Clarify the NT list API by separating the concept of a list from
// a node in a list. Although both are LIST_ENTRY's in the NT list
// API, there are subtle differences. For example, the head
// of a list is not embedded into any other structure the way the
// entries in a list are.
//
// Author:
//
// pmay 3-Apr-2002
//
// Environment:
//
// Kernel/user mode
//
// Revision History:
//
#pragma once
#ifndef NSULIST_H
#define NSULIST_H
#include "Nsu.h"
#ifdef __cplusplus
extern "C" { #endif
typedef LIST_ENTRY NSU_LIST_ENTRY; typedef PLIST_ENTRY PNSU_LIST_ENTRY;
typedef LIST_ENTRY NSU_LIST; typedef PLIST_ENTRY PNSU_LIST;
typedef struct _NSU_LIST_ITERATOR { PNSU_LIST pList; PNSU_LIST_ENTRY pCurrentEntry; } NSU_LIST_ITERATOR, * PNSU_LIST_ITERATOR;
// Description:
//
// API's to manipulate lists
//
VOID FORCEINLINE NsuListInitialize( OUT PNSU_LIST pList) { InitializeListHead(pList); }
BOOL FORCEINLINE NsuListIsEmpty( IN PNSU_LIST pList) { return IsListEmpty(pList); }
PNSU_LIST_ENTRY FORCEINLINE NsuListGetFront( IN PNSU_LIST pList) { return pList->Flink; }
PNSU_LIST_ENTRY FORCEINLINE NsuListGetBack( IN PNSU_LIST pList) { return pList->Blink; }
VOID FORCEINLINE NsuListInsertFront( IN PNSU_LIST pList, PNSU_LIST_ENTRY pEntry) { InsertHeadList(pList, pEntry); }
VOID FORCEINLINE NsuListInsertBack( IN PNSU_LIST pList, PNSU_LIST_ENTRY pEntry) { InsertTailList(pList, pEntry); }
PNSU_LIST_ENTRY FORCEINLINE NsuListRemoveFront( IN PNSU_LIST pList) { PNSU_LIST_ENTRY pEntry; if (IsListEmpty(pList)) { return NULL; }
pEntry = pList->Flink;
RemoveEntryList(pEntry); InitializeListHead(pEntry);
return pEntry; }
PNSU_LIST_ENTRY FORCEINLINE NsuListRemoveBack( IN PNSU_LIST pList) { PNSU_LIST_ENTRY pEntry; if (IsListEmpty(pList)) { return NULL; }
pEntry = pList->Blink;
RemoveEntryList(pEntry); InitializeListHead(pEntry);
return pEntry; }
// Description:
//
// API's to manipulate entries (nodes) in a list
//
#define NsuListEntryGetData(Address, Type, Field) \
CONTAINING_RECORD(Address, Type, Field)
VOID FORCEINLINE NsuListEntryInitialize( OUT PNSU_LIST_ENTRY pEntry) { InitializeListHead(pEntry); }
BOOL FORCEINLINE NsuListEntryIsMember( IN PNSU_LIST_ENTRY pEntry) { return IsListEmpty(pEntry); }
VOID FORCEINLINE NsuListEntryRemove( IN PNSU_LIST_ENTRY pEntry) { RemoveEntryList(pEntry); InitializeListHead(pEntry); }
VOID FORCEINLINE NsuListEntryInsertBefore( IN PNSU_LIST_ENTRY pEntryInList, IN PNSU_LIST_ENTRY pEntryToInsert) { InsertTailList(pEntryInList, pEntryToInsert); }
VOID FORCEINLINE NsuListEntryInsertAfter( IN PNSU_LIST_ENTRY pEntryInList, IN PNSU_LIST_ENTRY pEntryToInsert) { InsertHeadList(pEntryInList, pEntryToInsert); }
// Description:
//
// API's to iterate over lists
//
// Sample for using the iterator (includes removing during iteration):
//
// NSU_LIST List;
// NSU_LIST_ITERATOR Iterator;
// NSU_LIST_ENTRY* pEntry;
//
// NsuListIteratorInitialize(&Iterator, &List, NULL);
// while ( !NsuListIteratorAtEnd(&Iterator) )
// {
// pEntry = NsuListIteratorCurrent(&Iterator))
// pData = NsuListEntryGetData(pEntry, Type, Field);
//
// NsuListIteratorNext(&Iterator); // advance before any removing
//
// if (NeedToRemove(pData))
// {
// NsuListEntryRemove(pEntry);
// }
// }
//
VOID FORCEINLINE NsuListIteratorInitialize( OUT PNSU_LIST_ITERATOR pIterator, IN PNSU_LIST pList, IN OPTIONAL PNSU_LIST_ENTRY pEntryInList) // NULL = start at front
{ pIterator->pList = pList; pIterator->pCurrentEntry = (pEntryInList) ? pEntryInList : pList->Flink; }
BOOL FORCEINLINE NsuListIteratorAtEnd( IN PNSU_LIST_ITERATOR pIterator) { return (pIterator->pList == pIterator->pCurrentEntry); }
PNSU_LIST_ENTRY FORCEINLINE NsuListIteratorCurrent( IN PNSU_LIST_ITERATOR pIterator) { return pIterator->pCurrentEntry; }
VOID FORCEINLINE NsuListIteratorReset( IN PNSU_LIST_ITERATOR pIterator) { pIterator->pCurrentEntry = pIterator->pList->Flink; }
VOID FORCEINLINE NsuListIteratorNext( IN PNSU_LIST_ITERATOR pIterator) { pIterator->pCurrentEntry = pIterator->pCurrentEntry->Flink; }
VOID FORCEINLINE NsuListIteratorPrev( IN PNSU_LIST_ITERATOR pIterator) { pIterator->pCurrentEntry = pIterator->pCurrentEntry->Blink; }
// This wrapper does not work correctly in all cases and needs to be fixed. For now just
// use the C versions of everything
/*
// Description:
//
// C++ List api wrapper
//
#ifdef __cplusplus
class NsuListEntry { public: NsuListEntry() { NsuListEntryInitialize(&m_Entry); } ~NsuListEntry() { RtlZeroMemory(&m_Entry, sizeof(m_Entry)); }
PNSU_LIST_ENTRY Get() { return &m_Entry; } VOID Set(PNSU_LIST_ENTRY pEntry) { m_Entry = *pEntry; }
BOOL IsMember() { return NsuListEntryIsMember(Get()); }
VOID Remove() { return NsuListEntryRemove(&m_Entry); }
VOID InsertBefore(NsuListEntry* pSrc) { return NsuListEntryInsertBefore((PNSU_LIST_ENTRY)pSrc, &m_Entry); } VOID InsertAfter(NsuListEntry* pSrc) { return NsuListEntryInsertAfter((PNSU_LIST_ENTRY)pSrc, &m_Entry); }
private: NSU_LIST_ENTRY m_Entry; };
class NsuList { public: NsuList() { NsuListInitialize(&m_Head); }
PNSU_LIST Get() { return &m_Head; } PNSU_LIST GetFront(NsuListEntry& lEntry) { return NsuListGetFront(&m_Head); } PNSU_LIST GetBack(NsuListEntry& lEntry) { return NsuListGetBack(&m_Head); }
VOID RemoveFront(OUT OPTIONAL NsuListEntry* pEntry) { pEntry = (NsuListEntry*)NsuListRemoveFront(&m_Head); } VOID RemoveBack(OUT OPTIONAL NsuListEntry* pEntry) { pEntry = (NsuListEntry*)NsuListRemoveBack(&m_Head); }
VOID InsertFront(NsuListEntry* pEntry) { NsuListInsertFront(&m_Head, (PNSU_LIST_ENTRY)pEntry); } VOID InsertBack(NsuListEntry* pEntry) { NsuListInsertBack(&m_Head, (PNSU_LIST_ENTRY)pEntry); } VOID MoveToFront(NsuListEntry* pEntry); VOID MoveToBack(NsuListEntry* pEntry);
private: NSU_LIST m_Head; };
class NsuListIterator { public: NsuListIterator(NsuList* pList);
PNSU_LIST_ITERATOR Get() { return &m_Iterator; }
VOID Reset() { return NsuListIteratorReset(&(NSU_LIST_ITERATOR)m_Iterator); } VOID Next() { NsuListIteratorNext(&(NSU_LIST_ITERATOR)m_Iterator); } VOID Prev() { NsuListIteratorPrev(&(NSU_LIST_ITERATOR)m_Iterator); }
NsuListEntry* Current() { return (NsuListEntry*)NsuListIteratorCurrent(&(NSU_LIST_ITERATOR)m_Iterator); } BOOL AtEnd() { return NsuListIteratorAtEnd(&(NSU_LIST_ITERATOR)m_Iterator); }
private: NSU_LIST_ITERATOR m_Iterator; };
inline NsuListIterator::NsuListIterator(NsuList* pList) { NsuListIteratorInitialize(&(NSU_LIST_ITERATOR)m_Iterator, (PNSU_LIST)pList, 0); }
#endif
*/
#ifdef __cplusplus
} #endif
#endif // NSULIST_H
|