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.
 
 
 
 
 
 

399 lines
7.0 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name :
lstentry.h
Abstract:
Declares CListEntry and other 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 <locks.h>
#endif // !__LOCKS_H__
//--------------------------------------------------------------------
// 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:
CSpinLock 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:
CSpinLock 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__