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.
|
|
/*
* File: list.h * Author: John R. Douceur * Date: 19 November 1997 * Copyright (c) 1997-1999 Microsoft Corporation */
#ifndef _INC_LIST
#define _INC_LIST
#include <malloc.h>
template<class Class> class LinkedList; template<class Class> class NodePool;
template<class Class> class ListNode { public:
bool before_head() const {return previous_node == 0;} bool beyond_tail() const {return next_node == 0;}
Class &value() {return node_value;}
ListNode<Class> *next() const {return next_node;} ListNode<Class> *previous() const {return previous_node;}
ListNode<Class> *insert_before(); ListNode<Class> *insert_after();
ListNode<Class> *insert_before(Class object); ListNode<Class> *insert_after(Class object);
ListNode<Class> *insert_before(ListNode<Class> *node); ListNode<Class> *insert_after(ListNode<Class> *node);
ListNode<Class> *insert_before(LinkedList<Class> *list); ListNode<Class> *insert_after(LinkedList<Class> *list);
void remove(); ListNode<Class> *remove_forward(); ListNode<Class> *remove_backward();
friend class LinkedList<Class>; friend class NodePool<Class>;
~ListNode() {}
private: ListNode() {}
Class node_value; ListNode *next_node; ListNode *previous_node; };
template<class Class> class LinkedList { public:
LinkedList();
~LinkedList();
ListNode<Class> *head() const {return list_head.next_node;}
ListNode<Class> *tail() const {return list_tail.previous_node;}
bool is_empty() const {return list_head.next_node->next_node == 0;}
void flush();
friend class ListNode<Class>; friend class NodePool<Class>;
private:
ListNode<Class> list_head; ListNode<Class> list_tail; };
template<class Class> struct NodeGroup { NodeGroup<Class> *next_group; ListNode<Class> nodes[1]; };
template<class Class> class NodePool { public:
friend class ListNode<Class>; friend class LinkedList<Class>;
static void initialize(void); static void uninitialize(void);
private:
static ListNode<Class> *allocate();
static void deallocate(ListNode<Class> *node); static void deallocate(LinkedList<Class> *list);
static CRITICAL_SECTION critical_section;
static int group_size; static const int max_group_size; static NodeGroup<Class> *group_list; static ListNode<Class> *node_list; };
template<class Class> const int NodePool<Class>::max_group_size = 1024;
template<class Class> ListNode<Class> * ListNode<Class>::insert_before() { ListNode<Class> *node = NodePool<Class>::allocate(); if (node == 0) { return 0; } node->previous_node = previous_node; node->next_node = this; previous_node->next_node = node; previous_node = node; return node; }
template<class Class> ListNode<Class> * ListNode<Class>::insert_after() { ListNode<Class> *node = NodePool<Class>::allocate(); if (node == 0) { return 0; } node->next_node = next_node; node->previous_node = this; next_node->previous_node = node; next_node = node; return node; }
template<class Class> ListNode<Class> * ListNode<Class>::insert_before( Class object) { ListNode<Class> *node = NodePool<Class>::allocate(); if (node == 0) { return 0; } node->previous_node = previous_node; node->next_node = this; node->node_value = object; previous_node->next_node = node; previous_node = node; return node; }
template<class Class> ListNode<Class> * ListNode<Class>::insert_after( Class object) { ListNode<Class> *node = NodePool<Class>::allocate(); if (node == 0) { return 0; } node->next_node = next_node; node->previous_node = this; node->node_value = object; next_node->previous_node = node; next_node = node; return node; }
template<class Class> ListNode<Class> * ListNode<Class>::insert_before( ListNode<Class> *node) { node->previous_node->next_node = node->next_node; node->next_node->previous_node = node->previous_node; node->previous_node = previous_node; node->next_node = this; previous_node->next_node = node; previous_node = node; return node; }
template<class Class> ListNode<Class> * ListNode<Class>::insert_after( ListNode<Class> *node) { node->previous_node->next_node = node->next_node; node->next_node->previous_node = node->previous_node; node->next_node = next_node; node->previous_node = this; next_node->previous_node = node; next_node = node; return node; }
template<class Class> ListNode<Class> * ListNode<Class>::insert_before( LinkedList<Class> *list) { if (!list->is_empty()) { ListNode<Class> *old_head = list->list_head.next_node; previous_node->next_node = old_head; old_head->previous_node = previous_node; previous_node = list->list_tail.previous_node; previous_node->next_node = this; list->list_head.next_node = &list->list_tail; list->list_tail.previous_node = &list->list_head; return old_head; } else { return this; } }
template<class Class> ListNode<Class> * ListNode<Class>::insert_after( LinkedList<Class> *list) { if (!list->is_empty()) { ListNode<Class> *old_tail = list->list_tail.previous_node; next_node->previous_node = old_tail; old_tail->next_node = next_node; next_node = list->list_head.next_node; next_node->previous_node = this; list->list_tail.previous_node = &list->list_head; list->list_head.next_node = &list->list_tail; return old_tail; } else { return this; } }
template<class Class> void ListNode<Class>::remove() { previous_node->next_node = next_node; next_node->previous_node = previous_node; NodePool<Class>::deallocate(this); }
template<class Class> ListNode<Class> * ListNode<Class>::remove_forward() { ListNode<Class> *node = next_node; previous_node->next_node = next_node; next_node->previous_node = previous_node; NodePool<Class>::deallocate(this); return node; }
template<class Class> ListNode<Class> * ListNode<Class>::remove_backward() { ListNode<Class> *node = previous_node; previous_node->next_node = next_node; next_node->previous_node = previous_node; NodePool<Class>::deallocate(this); return node; }
template<class Class> LinkedList<Class>::LinkedList() { list_head.next_node = &list_tail; list_head.previous_node = 0; list_tail.next_node = 0; list_tail.previous_node = &list_head; }
template<class Class> LinkedList<Class>::~LinkedList() { NodePool<Class>::deallocate(this); }
template<class Class> void LinkedList<Class>::flush() { NodePool<Class>::deallocate(this); }
template<class Class> int NodePool<Class>::group_size = 1; template<class Class> NodeGroup<Class> * NodePool<Class>::group_list = 0; template<class Class> ListNode<Class> * NodePool<Class>::node_list = 0; template<class Class> CRITICAL_SECTION NodePool<Class>::critical_section = {0};
template<class Class> void NodePool<Class>::initialize() { InitializeCriticalSection(&critical_section); }
template<class Class> void NodePool<Class>::uninitialize() { DeleteCriticalSection(&critical_section); }
template<class Class> ListNode<Class> * NodePool<Class>::allocate() {
EnterCriticalSection(&critical_section); if (node_list == 0) { NodeGroup<Class> *node_group = (NodeGroup<Class> *)malloc(sizeof(NodeGroup<Class>) + (group_size - 1) * sizeof(ListNode<Class>)); while (node_group == 0 && group_size > 1) { group_size /= 2; node_group = (NodeGroup<Class> *)malloc(sizeof(NodeGroup<Class>) + (group_size - 1) * sizeof(ListNode<Class>)); } if (node_group == 0) { LeaveCriticalSection(&critical_section); return 0; } node_group->next_group = group_list; group_list = node_group; for (int index = 0; index < group_size; index++) { node_group->nodes[index].next_node = node_list; node_list = &node_group->nodes[index]; } group_size *= 2; if (group_size > max_group_size) { group_size = max_group_size; } } ListNode<Class> *node = node_list; node_list = node->next_node; LeaveCriticalSection(&critical_section); return node; }
template<class Class> void NodePool<Class>::deallocate( ListNode<Class> *node) { EnterCriticalSection(&critical_section);
node->next_node = node_list; node_list = node;
LeaveCriticalSection(&critical_section); }
template<class Class> void NodePool<Class>::deallocate( LinkedList<Class> *list) { EnterCriticalSection(&critical_section); if (!list->is_empty()) { list->list_tail.previous_node->next_node = node_list; node_list = list->list_head.next_node; list->list_tail.previous_node = &list->list_head; list->list_head.next_node = &list->list_tail; } LeaveCriticalSection(&critical_section);
}
#endif /* _INC_LIST */
|