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.

261 lines
8.4 KiB

20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
  1. /*****************************************************************************
  2. Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free Software
  5. Foundation; version 2 of the License.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along with
  10. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  11. Place, Suite 330, Boston, MA 02111-1307 USA
  12. *****************************************************************************/
  13. /******************************************************************//**
  14. @file include/ut0lst.h
  15. List utilities
  16. Created 9/10/1995 Heikki Tuuri
  17. ***********************************************************************/
  18. #ifndef ut0lst_h
  19. #define ut0lst_h
  20. #include "univ.i"
  21. /* This module implements the two-way linear list which should be used
  22. if a list is used in the database. Note that a single struct may belong
  23. to two or more lists, provided that the list are given different names.
  24. An example of the usage of the lists can be found in fil0fil.c. */
  25. /*******************************************************************//**
  26. This macro expands to the unnamed type definition of a struct which acts
  27. as the two-way list base node. The base node contains pointers
  28. to both ends of the list and a count of nodes in the list (excluding
  29. the base node from the count).
  30. @param TYPE the name of the list node data type */
  31. #define UT_LIST_BASE_NODE_T(TYPE)\
  32. struct {\
  33. ulint count; /*!< count of nodes in list */\
  34. TYPE * start; /*!< pointer to list start, NULL if empty */\
  35. TYPE * end; /*!< pointer to list end, NULL if empty */\
  36. }\
  37. /*******************************************************************//**
  38. This macro expands to the unnamed type definition of a struct which
  39. should be embedded in the nodes of the list, the node type must be a struct.
  40. This struct contains the pointers to next and previous nodes in the list.
  41. The name of the field in the node struct should be the name given
  42. to the list.
  43. @param TYPE the list node type name */
  44. /* Example:
  45. typedef struct LRU_node_struct LRU_node_t;
  46. struct LRU_node_struct {
  47. UT_LIST_NODE_T(LRU_node_t) LRU_list;
  48. ...
  49. }
  50. The example implements an LRU list of name LRU_list. Its nodes are of type
  51. LRU_node_t. */
  52. #define UT_LIST_NODE_T(TYPE)\
  53. struct {\
  54. TYPE * prev; /*!< pointer to the previous node,\
  55. NULL if start of list */\
  56. TYPE * next; /*!< pointer to next node, NULL if end of list */\
  57. }\
  58. /*******************************************************************//**
  59. Initializes the base node of a two-way list.
  60. @param BASE the list base node
  61. */
  62. #define UT_LIST_INIT(BASE)\
  63. {\
  64. (BASE).count = 0;\
  65. (BASE).start = NULL;\
  66. (BASE).end = NULL;\
  67. }\
  68. /*******************************************************************//**
  69. Adds the node as the first element in a two-way linked list.
  70. @param NAME list name
  71. @param BASE the base node (not a pointer to it)
  72. @param N pointer to the node to be added to the list.
  73. */
  74. #define UT_LIST_ADD_FIRST(NAME, BASE, N)\
  75. {\
  76. ut_ad(N);\
  77. ((BASE).count)++;\
  78. ((N)->NAME).next = (BASE).start;\
  79. ((N)->NAME).prev = NULL;\
  80. if (UNIV_LIKELY((BASE).start != NULL)) {\
  81. ut_ad((BASE).start != (N));\
  82. (((BASE).start)->NAME).prev = (N);\
  83. }\
  84. (BASE).start = (N);\
  85. if (UNIV_UNLIKELY((BASE).end == NULL)) {\
  86. (BASE).end = (N);\
  87. }\
  88. }\
  89. /*******************************************************************//**
  90. Adds the node as the last element in a two-way linked list.
  91. @param NAME list name
  92. @param BASE the base node (not a pointer to it)
  93. @param N pointer to the node to be added to the list
  94. */
  95. #define UT_LIST_ADD_LAST(NAME, BASE, N)\
  96. {\
  97. ut_ad(N);\
  98. ((BASE).count)++;\
  99. ((N)->NAME).prev = (BASE).end;\
  100. ((N)->NAME).next = NULL;\
  101. if ((BASE).end != NULL) {\
  102. ut_ad((BASE).end != (N));\
  103. (((BASE).end)->NAME).next = (N);\
  104. }\
  105. (BASE).end = (N);\
  106. if ((BASE).start == NULL) {\
  107. (BASE).start = (N);\
  108. }\
  109. }\
  110. /*******************************************************************//**
  111. Inserts a NODE2 after NODE1 in a list.
  112. @param NAME list name
  113. @param BASE the base node (not a pointer to it)
  114. @param NODE1 pointer to node after which NODE2 is inserted
  115. @param NODE2 pointer to node being inserted after NODE1
  116. */
  117. #define UT_LIST_INSERT_AFTER(NAME, BASE, NODE1, NODE2)\
  118. {\
  119. ut_ad(NODE1);\
  120. ut_ad(NODE2);\
  121. ut_ad((NODE1) != (NODE2));\
  122. ((BASE).count)++;\
  123. ((NODE2)->NAME).prev = (NODE1);\
  124. ((NODE2)->NAME).next = ((NODE1)->NAME).next;\
  125. if (((NODE1)->NAME).next != NULL) {\
  126. ((((NODE1)->NAME).next)->NAME).prev = (NODE2);\
  127. }\
  128. ((NODE1)->NAME).next = (NODE2);\
  129. if ((BASE).end == (NODE1)) {\
  130. (BASE).end = (NODE2);\
  131. }\
  132. }\
  133. #ifdef UNIV_LIST_DEBUG
  134. /** Invalidate the pointers in a list node.
  135. @param NAME list name
  136. @param N pointer to the node that was removed */
  137. # define UT_LIST_REMOVE_CLEAR(NAME, N) \
  138. ((N)->NAME.prev = (N)->NAME.next = (void*) -1)
  139. #else
  140. /** Invalidate the pointers in a list node.
  141. @param NAME list name
  142. @param N pointer to the node that was removed */
  143. # define UT_LIST_REMOVE_CLEAR(NAME, N) while (0)
  144. #endif
  145. /*******************************************************************//**
  146. Removes a node from a two-way linked list.
  147. @param NAME list name
  148. @param BASE the base node (not a pointer to it)
  149. @param N pointer to the node to be removed from the list
  150. */
  151. #define UT_LIST_REMOVE(NAME, BASE, N) \
  152. do { \
  153. ut_ad(N); \
  154. ut_a((BASE).count > 0); \
  155. ((BASE).count)--; \
  156. if (((N)->NAME).next != NULL) { \
  157. ((((N)->NAME).next)->NAME).prev = ((N)->NAME).prev; \
  158. } else { \
  159. (BASE).end = ((N)->NAME).prev; \
  160. } \
  161. if (((N)->NAME).prev != NULL) { \
  162. ((((N)->NAME).prev)->NAME).next = ((N)->NAME).next; \
  163. } else { \
  164. (BASE).start = ((N)->NAME).next; \
  165. } \
  166. UT_LIST_REMOVE_CLEAR(NAME, N); \
  167. } while (0)
  168. /********************************************************************//**
  169. Gets the next node in a two-way list.
  170. @param NAME list name
  171. @param N pointer to a node
  172. @return the successor of N in NAME, or NULL */
  173. #define UT_LIST_GET_NEXT(NAME, N)\
  174. (((N)->NAME).next)
  175. /********************************************************************//**
  176. Gets the previous node in a two-way list.
  177. @param NAME list name
  178. @param N pointer to a node
  179. @return the predecessor of N in NAME, or NULL */
  180. #define UT_LIST_GET_PREV(NAME, N)\
  181. (((N)->NAME).prev)
  182. /********************************************************************//**
  183. Alternative macro to get the number of nodes in a two-way list, i.e.,
  184. its length.
  185. @param BASE the base node (not a pointer to it).
  186. @return the number of nodes in the list */
  187. #define UT_LIST_GET_LEN(BASE)\
  188. (BASE).count
  189. /********************************************************************//**
  190. Gets the first node in a two-way list.
  191. @param BASE the base node (not a pointer to it)
  192. @return first node, or NULL if the list is empty */
  193. #define UT_LIST_GET_FIRST(BASE)\
  194. (BASE).start
  195. /********************************************************************//**
  196. Gets the last node in a two-way list.
  197. @param BASE the base node (not a pointer to it)
  198. @return last node, or NULL if the list is empty */
  199. #define UT_LIST_GET_LAST(BASE)\
  200. (BASE).end
  201. /********************************************************************//**
  202. Checks the consistency of a two-way list.
  203. @param NAME the name of the list
  204. @param TYPE node type
  205. @param BASE base node (not a pointer to it)
  206. @param ASSERTION a condition on ut_list_node_313 */
  207. #define UT_LIST_VALIDATE(NAME, TYPE, BASE, ASSERTION) \
  208. do { \
  209. ulint ut_list_i_313; \
  210. TYPE* ut_list_node_313; \
  211. \
  212. ut_list_node_313 = (BASE).start; \
  213. \
  214. for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
  215. ut_a(ut_list_node_313); \
  216. ASSERTION; \
  217. ut_ad((ut_list_node_313->NAME).next || !ut_list_i_313); \
  218. ut_list_node_313 = (ut_list_node_313->NAME).next; \
  219. } \
  220. \
  221. ut_a(ut_list_node_313 == NULL); \
  222. \
  223. ut_list_node_313 = (BASE).end; \
  224. \
  225. for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
  226. ut_a(ut_list_node_313); \
  227. ASSERTION; \
  228. ut_ad((ut_list_node_313->NAME).prev || !ut_list_i_313); \
  229. ut_list_node_313 = (ut_list_node_313->NAME).prev; \
  230. } \
  231. \
  232. ut_a(ut_list_node_313 == NULL); \
  233. } while (0)
  234. #endif