/*++ Copyright (c) 1999-2000 Microsoft Corporation Module Name : LstEntry.h Abstract: Declares CListEntry and other intrusive singly- and doubly-linked lists Author: George V. Reilly (GeorgeRe) 02-Mar-1999 Environment: Win32 - User Mode Project: Internet Information Server RunTime Library Revision History: --*/ #ifndef __LSTENTRY_H__ #define __LSTENTRY_H__ #ifndef __LOCKS_H__ # include #endif // !__LOCKS_H__ #ifndef LSTENTRY_LOCK #ifdef LOCKS_KERNEL_MODE #define LSTENTRY_LOCK CKSpinLock #else // !LOCKS_KERNEL_MODE #define LSTENTRY_LOCK CSpinLock #endif // !LOCKS_KERNEL_MODE #endif // !LSTENTRY_LOCK // TODO: // * Add STL-style iterators: begin(), end(), operator++(), etc // * Templatize the lists, so that you can avoid the CONTAINING_RECORD goo //-------------------------------------------------------------------- // CSingleListEntry: a node in a singly-linked list. Usually embedded // within larger structures. //-------------------------------------------------------------------- class CSingleListEntry { public: CSingleListEntry* Next; // forward link }; //-------------------------------------------------------------------- // A non-threadsafe singly linked list //-------------------------------------------------------------------- class IRTL_DLLEXP CSingleList { protected: CSingleListEntry m_sleHead; // external head node public: CSingleList() { m_sleHead.Next = NULL; } ~CSingleList() { IRTLASSERT(IsEmpty()); } bool IsEmpty() const { return m_sleHead.Next == NULL; } CSingleListEntry* const Pop() { CSingleListEntry* psle = m_sleHead.Next; if (psle != NULL) m_sleHead.Next = psle->Next; return psle; } void Push( CSingleListEntry* const psle) { psle->Next = m_sleHead.Next; m_sleHead.Next = psle; } }; //-------------------------------------------------------------------- // A threadsafe singly linked list //-------------------------------------------------------------------- class IRTL_DLLEXP CLockedSingleList { protected: LSTENTRY_LOCK m_lock; CSingleList m_list; public: #ifdef LOCK_INSTRUMENTATION CLockedSingleList() : m_lock(NULL) {} #endif // LOCK_INSTRUMENTATION void Lock() { m_lock.WriteLock(); } void Unlock() { m_lock.WriteUnlock(); } bool IsLocked() const { return m_lock.IsWriteLocked(); } bool IsUnlocked() const { return m_lock.IsWriteUnlocked(); } bool IsEmpty() const { return m_list.IsEmpty(); } CSingleListEntry* const Pop() { Lock(); CSingleListEntry* const psle = m_list.Pop(); Unlock(); return psle; } void Push( CSingleListEntry* const psle) { Lock(); m_list.Push(psle); Unlock(); } }; //-------------------------------------------------------------------- // CListEntry: a node in a circular doubly-linked list. Usually embedded // within larger structures. //-------------------------------------------------------------------- class CListEntry { public: CListEntry* Flink; // forward link CListEntry* Blink; // backward link }; //-------------------------------------------------------------------- // A non-threadsafe circular doubly linked list //-------------------------------------------------------------------- class IRTL_DLLEXP CDoubleList { protected: CListEntry m_leHead; // external head node public: CDoubleList() { m_leHead.Flink = m_leHead.Blink = &m_leHead; } ~CDoubleList() { IRTLASSERT(m_leHead.Flink != NULL && m_leHead.Blink != NULL); IRTLASSERT(IsEmpty()); } bool IsEmpty() const { return m_leHead.Flink == &m_leHead; } void InsertHead( CListEntry* const ple) { ple->Blink = &m_leHead; ple->Flink = m_leHead.Flink; ple->Flink->Blink = ple; m_leHead.Flink = ple; } void InsertTail( CListEntry* const ple) { ple->Flink = &m_leHead; ple->Blink = m_leHead.Blink; ple->Blink->Flink = ple; m_leHead.Blink = ple; } const CListEntry* const HeadNode() const { return &m_leHead; } CListEntry* const First() const { return m_leHead.Flink; } CListEntry* const RemoveHead() { CListEntry* ple = First(); RemoveEntry(ple); return ple; } CListEntry* const Last() const { return m_leHead.Blink; } CListEntry* const RemoveTail() { CListEntry* ple = Last(); RemoveEntry(ple); return ple; } static void RemoveEntry( CListEntry* const ple) { CListEntry* const pleOldBlink = ple->Blink; IRTLASSERT(pleOldBlink != NULL); CListEntry* const pleOldFlink = ple->Flink; IRTLASSERT(pleOldFlink != NULL); pleOldBlink->Flink = pleOldFlink; pleOldFlink->Blink = pleOldBlink; } }; //-------------------------------------------------------------------- // A threadsafe circular doubly linked list //-------------------------------------------------------------------- class IRTL_DLLEXP CLockedDoubleList { protected: LSTENTRY_LOCK m_lock; CDoubleList m_list; public: #ifdef LOCK_INSTRUMENTATION CLockedDoubleList() : m_lock(NULL) {} #endif // LOCK_INSTRUMENTATION void Lock() { m_lock.WriteLock(); } void Unlock() { m_lock.WriteUnlock(); } bool IsLocked() const { return m_lock.IsWriteLocked(); } bool IsUnlocked() const { return m_lock.IsWriteUnlocked(); } bool IsEmpty() const { return m_list.IsEmpty(); } void InsertHead( CListEntry* const ple) { Lock(); m_list.InsertHead(ple); Unlock(); } void InsertTail( CListEntry* const ple) { Lock(); m_list.InsertTail(ple); Unlock(); } // not threadsafe const CListEntry* const HeadNode() const { return m_list.HeadNode(); } // not threadsafe CListEntry* const First() { return m_list.First(); } CListEntry* const RemoveHead() { Lock(); CListEntry* const ple = m_list.RemoveHead(); Unlock(); return ple; } // not threadsafe CListEntry* const Last() { return m_list.Last(); } CListEntry* const RemoveTail() { Lock(); CListEntry* const ple = m_list.RemoveTail(); Unlock(); return ple; } void RemoveEntry( CListEntry* const ple) { Lock(); m_list.RemoveEntry(ple); Unlock(); } }; #ifndef CONTAINING_RECORD // // Calculate the address of the base of the structure given its type, and an // address of a field within the structure. // #define CONTAINING_RECORD(address, type, field) \ ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field))) #endif // !CONTAINING_RECORD #endif // __LSTENTRY_H__