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.

406 lines
8.3 KiB

  1. /*
  2. * File: list.h
  3. * Author: John R. Douceur
  4. * Date: 19 November 1997
  5. * Copyright (c) 1997-1999 Microsoft Corporation
  6. */
  7. #ifndef _INC_LIST
  8. #define _INC_LIST
  9. #include <malloc.h>
  10. template<class Class> class LinkedList;
  11. template<class Class> class NodePool;
  12. template<class Class> class ListNode
  13. {
  14. public:
  15. bool before_head() const {return previous_node == 0;}
  16. bool beyond_tail() const {return next_node == 0;}
  17. Class &value() {return node_value;}
  18. ListNode<Class> *next() const {return next_node;}
  19. ListNode<Class> *previous() const {return previous_node;}
  20. ListNode<Class> *insert_before();
  21. ListNode<Class> *insert_after();
  22. ListNode<Class> *insert_before(Class object);
  23. ListNode<Class> *insert_after(Class object);
  24. ListNode<Class> *insert_before(ListNode<Class> *node);
  25. ListNode<Class> *insert_after(ListNode<Class> *node);
  26. ListNode<Class> *insert_before(LinkedList<Class> *list);
  27. ListNode<Class> *insert_after(LinkedList<Class> *list);
  28. void remove();
  29. ListNode<Class> *remove_forward();
  30. ListNode<Class> *remove_backward();
  31. friend class LinkedList<Class>;
  32. friend class NodePool<Class>;
  33. ~ListNode() {}
  34. private:
  35. ListNode() {}
  36. Class node_value;
  37. ListNode *next_node;
  38. ListNode *previous_node;
  39. };
  40. template<class Class> class LinkedList
  41. {
  42. public:
  43. LinkedList();
  44. ~LinkedList();
  45. ListNode<Class> *head() const {return list_head.next_node;}
  46. ListNode<Class> *tail() const {return list_tail.previous_node;}
  47. bool is_empty() const {return list_head.next_node->next_node == 0;}
  48. void flush();
  49. friend class ListNode<Class>;
  50. friend class NodePool<Class>;
  51. private:
  52. ListNode<Class> list_head;
  53. ListNode<Class> list_tail;
  54. };
  55. template<class Class> struct NodeGroup
  56. {
  57. NodeGroup<Class> *next_group;
  58. ListNode<Class> nodes[1];
  59. };
  60. template<class Class> class NodePool
  61. {
  62. public:
  63. friend class ListNode<Class>;
  64. friend class LinkedList<Class>;
  65. static void initialize(void);
  66. static void uninitialize(void);
  67. private:
  68. static ListNode<Class> *allocate();
  69. static void deallocate(ListNode<Class> *node);
  70. static void deallocate(LinkedList<Class> *list);
  71. static CRITICAL_SECTION critical_section;
  72. static int group_size;
  73. static const int max_group_size;
  74. static NodeGroup<Class> *group_list;
  75. static ListNode<Class> *node_list;
  76. };
  77. template<class Class> const int NodePool<Class>::max_group_size = 1024;
  78. template<class Class>
  79. ListNode<Class> *
  80. ListNode<Class>::insert_before()
  81. {
  82. ListNode<Class> *node = NodePool<Class>::allocate();
  83. if (node == 0)
  84. {
  85. return 0;
  86. }
  87. node->previous_node = previous_node;
  88. node->next_node = this;
  89. previous_node->next_node = node;
  90. previous_node = node;
  91. return node;
  92. }
  93. template<class Class>
  94. ListNode<Class> *
  95. ListNode<Class>::insert_after()
  96. {
  97. ListNode<Class> *node = NodePool<Class>::allocate();
  98. if (node == 0)
  99. {
  100. return 0;
  101. }
  102. node->next_node = next_node;
  103. node->previous_node = this;
  104. next_node->previous_node = node;
  105. next_node = node;
  106. return node;
  107. }
  108. template<class Class>
  109. ListNode<Class> *
  110. ListNode<Class>::insert_before(
  111. Class object)
  112. {
  113. ListNode<Class> *node = NodePool<Class>::allocate();
  114. if (node == 0)
  115. {
  116. return 0;
  117. }
  118. node->previous_node = previous_node;
  119. node->next_node = this;
  120. node->node_value = object;
  121. previous_node->next_node = node;
  122. previous_node = node;
  123. return node;
  124. }
  125. template<class Class>
  126. ListNode<Class> *
  127. ListNode<Class>::insert_after(
  128. Class object)
  129. {
  130. ListNode<Class> *node = NodePool<Class>::allocate();
  131. if (node == 0)
  132. {
  133. return 0;
  134. }
  135. node->next_node = next_node;
  136. node->previous_node = this;
  137. node->node_value = object;
  138. next_node->previous_node = node;
  139. next_node = node;
  140. return node;
  141. }
  142. template<class Class>
  143. ListNode<Class> *
  144. ListNode<Class>::insert_before(
  145. ListNode<Class> *node)
  146. {
  147. node->previous_node->next_node = node->next_node;
  148. node->next_node->previous_node = node->previous_node;
  149. node->previous_node = previous_node;
  150. node->next_node = this;
  151. previous_node->next_node = node;
  152. previous_node = node;
  153. return node;
  154. }
  155. template<class Class>
  156. ListNode<Class> *
  157. ListNode<Class>::insert_after(
  158. ListNode<Class> *node)
  159. {
  160. node->previous_node->next_node = node->next_node;
  161. node->next_node->previous_node = node->previous_node;
  162. node->next_node = next_node;
  163. node->previous_node = this;
  164. next_node->previous_node = node;
  165. next_node = node;
  166. return node;
  167. }
  168. template<class Class>
  169. ListNode<Class> *
  170. ListNode<Class>::insert_before(
  171. LinkedList<Class> *list)
  172. {
  173. if (!list->is_empty())
  174. {
  175. ListNode<Class> *old_head = list->list_head.next_node;
  176. previous_node->next_node = old_head;
  177. old_head->previous_node = previous_node;
  178. previous_node = list->list_tail.previous_node;
  179. previous_node->next_node = this;
  180. list->list_head.next_node = &list->list_tail;
  181. list->list_tail.previous_node = &list->list_head;
  182. return old_head;
  183. }
  184. else
  185. {
  186. return this;
  187. }
  188. }
  189. template<class Class>
  190. ListNode<Class> *
  191. ListNode<Class>::insert_after(
  192. LinkedList<Class> *list)
  193. {
  194. if (!list->is_empty())
  195. {
  196. ListNode<Class> *old_tail = list->list_tail.previous_node;
  197. next_node->previous_node = old_tail;
  198. old_tail->next_node = next_node;
  199. next_node = list->list_head.next_node;
  200. next_node->previous_node = this;
  201. list->list_tail.previous_node = &list->list_head;
  202. list->list_head.next_node = &list->list_tail;
  203. return old_tail;
  204. }
  205. else
  206. {
  207. return this;
  208. }
  209. }
  210. template<class Class>
  211. void
  212. ListNode<Class>::remove()
  213. {
  214. previous_node->next_node = next_node;
  215. next_node->previous_node = previous_node;
  216. NodePool<Class>::deallocate(this);
  217. }
  218. template<class Class>
  219. ListNode<Class> *
  220. ListNode<Class>::remove_forward()
  221. {
  222. ListNode<Class> *node = next_node;
  223. previous_node->next_node = next_node;
  224. next_node->previous_node = previous_node;
  225. NodePool<Class>::deallocate(this);
  226. return node;
  227. }
  228. template<class Class>
  229. ListNode<Class> *
  230. ListNode<Class>::remove_backward()
  231. {
  232. ListNode<Class> *node = previous_node;
  233. previous_node->next_node = next_node;
  234. next_node->previous_node = previous_node;
  235. NodePool<Class>::deallocate(this);
  236. return node;
  237. }
  238. template<class Class>
  239. LinkedList<Class>::LinkedList()
  240. {
  241. list_head.next_node = &list_tail;
  242. list_head.previous_node = 0;
  243. list_tail.next_node = 0;
  244. list_tail.previous_node = &list_head;
  245. }
  246. template<class Class>
  247. LinkedList<Class>::~LinkedList()
  248. {
  249. NodePool<Class>::deallocate(this);
  250. }
  251. template<class Class>
  252. void
  253. LinkedList<Class>::flush()
  254. {
  255. NodePool<Class>::deallocate(this);
  256. }
  257. template<class Class> int NodePool<Class>::group_size = 1;
  258. template<class Class> NodeGroup<Class> * NodePool<Class>::group_list = 0;
  259. template<class Class> ListNode<Class> * NodePool<Class>::node_list = 0;
  260. template<class Class> CRITICAL_SECTION NodePool<Class>::critical_section = {0};
  261. template<class Class>
  262. void NodePool<Class>::initialize()
  263. {
  264. InitializeCriticalSection(&critical_section);
  265. }
  266. template<class Class>
  267. void NodePool<Class>::uninitialize()
  268. {
  269. DeleteCriticalSection(&critical_section);
  270. }
  271. template<class Class>
  272. ListNode<Class> *
  273. NodePool<Class>::allocate()
  274. {
  275. EnterCriticalSection(&critical_section);
  276. if (node_list == 0)
  277. {
  278. NodeGroup<Class> *node_group =
  279. (NodeGroup<Class> *)malloc(sizeof(NodeGroup<Class>) +
  280. (group_size - 1) * sizeof(ListNode<Class>));
  281. while (node_group == 0 && group_size > 1)
  282. {
  283. group_size /= 2;
  284. node_group =
  285. (NodeGroup<Class> *)malloc(sizeof(NodeGroup<Class>) +
  286. (group_size - 1) * sizeof(ListNode<Class>));
  287. }
  288. if (node_group == 0)
  289. {
  290. LeaveCriticalSection(&critical_section);
  291. return 0;
  292. }
  293. node_group->next_group = group_list;
  294. group_list = node_group;
  295. for (int index = 0; index < group_size; index++)
  296. {
  297. node_group->nodes[index].next_node = node_list;
  298. node_list = &node_group->nodes[index];
  299. }
  300. group_size *= 2;
  301. if (group_size > max_group_size)
  302. {
  303. group_size = max_group_size;
  304. }
  305. }
  306. ListNode<Class> *node = node_list;
  307. node_list = node->next_node;
  308. LeaveCriticalSection(&critical_section);
  309. return node;
  310. }
  311. template<class Class>
  312. void
  313. NodePool<Class>::deallocate(
  314. ListNode<Class> *node)
  315. {
  316. EnterCriticalSection(&critical_section);
  317. node->next_node = node_list;
  318. node_list = node;
  319. LeaveCriticalSection(&critical_section);
  320. }
  321. template<class Class>
  322. void
  323. NodePool<Class>::deallocate(
  324. LinkedList<Class> *list)
  325. {
  326. EnterCriticalSection(&critical_section);
  327. if (!list->is_empty())
  328. {
  329. list->list_tail.previous_node->next_node = node_list;
  330. node_list = list->list_head.next_node;
  331. list->list_tail.previous_node = &list->list_head;
  332. list->list_head.next_node = &list->list_tail;
  333. }
  334. LeaveCriticalSection(&critical_section);
  335. }
  336. #endif /* _INC_LIST */