1
/*****************************************************************************
3
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/******************************************************************//**
20
@file include/ut0lst.h
23
Created 9/10/1995 Heikki Tuuri
24
***********************************************************************/
31
/* This module implements the two-way linear list which should be used
32
if a list is used in the database. Note that a single struct may belong
33
to two or more lists, provided that the list are given different names.
34
An example of the usage of the lists can be found in fil0fil.c. */
36
/*******************************************************************//**
37
This macro expands to the unnamed type definition of a struct which acts
38
as the two-way list base node. The base node contains pointers
39
to both ends of the list and a count of nodes in the list (excluding
40
the base node from the count).
41
@param TYPE the name of the list node data type */
44
class ut_list_base_node
47
size_t count; /*!< count of nodes in list */\
48
T * start; /*!< pointer to list start, NULL if empty */\
49
T * end; /*!< pointer to list end, NULL if empty */\
51
#define UT_LIST_BASE_NODE_T(TYPE) ut_list_base_node<TYPE>
53
#define UT_LIST_BASE_NODE_T(TYPE) int
56
/*******************************************************************//**
57
This macro expands to the unnamed type definition of a struct which
58
should be embedded in the nodes of the list, the node type must be a struct.
59
This struct contains the pointers to next and previous nodes in the list.
60
The name of the field in the node struct should be the name given
62
@param TYPE the list node type name */
64
typedef struct LRU_node_struct LRU_node_t;
65
struct LRU_node_struct {
66
UT_LIST_NODE_T(LRU_node_t) LRU_list;
69
The example implements an LRU list of name LRU_list. Its nodes are of type
72
#define UT_LIST_NODE_T(TYPE)\
74
TYPE * prev; /*!< pointer to the previous node,\
75
NULL if start of list */\
76
TYPE * next; /*!< pointer to next node, NULL if end of list */\
79
/*******************************************************************//**
80
Initializes the base node of a two-way list.
81
@param BASE the list base node
83
#define UT_LIST_INIT(BASE)\
90
/*******************************************************************//**
91
Adds the node as the first element in a two-way linked list.
93
@param BASE the base node (not a pointer to it)
94
@param N pointer to the node to be added to the list.
96
#define UT_LIST_ADD_FIRST(NAME, BASE, N)\
100
((N)->NAME).next = (BASE).start;\
101
((N)->NAME).prev = NULL;\
102
if (UNIV_LIKELY((BASE).start != NULL)) {\
103
ut_ad((BASE).start != (N));\
104
(((BASE).start)->NAME).prev = (N);\
107
if (UNIV_UNLIKELY((BASE).end == NULL)) {\
112
/*******************************************************************//**
113
Adds the node as the last element in a two-way linked list.
114
@param NAME list name
115
@param BASE the base node (not a pointer to it)
116
@param N pointer to the node to be added to the list
118
#define UT_LIST_ADD_LAST(NAME, BASE, N)\
122
((N)->NAME).prev = (BASE).end;\
123
((N)->NAME).next = NULL;\
124
if ((BASE).end != NULL) {\
125
ut_ad((BASE).end != (N));\
126
(((BASE).end)->NAME).next = (N);\
129
if ((BASE).start == NULL) {\
134
/*******************************************************************//**
135
Inserts a NODE2 after NODE1 in a list.
136
@param NAME list name
137
@param BASE the base node (not a pointer to it)
138
@param NODE1 pointer to node after which NODE2 is inserted
139
@param NODE2 pointer to node being inserted after NODE1
141
#define UT_LIST_INSERT_AFTER(NAME, BASE, NODE1, NODE2)\
145
ut_ad((NODE1) != (NODE2));\
147
((NODE2)->NAME).prev = (NODE1);\
148
((NODE2)->NAME).next = ((NODE1)->NAME).next;\
149
if (((NODE1)->NAME).next != NULL) {\
150
((((NODE1)->NAME).next)->NAME).prev = (NODE2);\
152
((NODE1)->NAME).next = (NODE2);\
153
if ((BASE).end == (NODE1)) {\
154
(BASE).end = (NODE2);\
158
#ifdef UNIV_LIST_DEBUG
159
/** Invalidate the pointers in a list node.
160
@param NAME list name
161
@param N pointer to the node that was removed */
162
# define UT_LIST_REMOVE_CLEAR(NAME, N) \
163
((N)->NAME.prev = (N)->NAME.next = (void*) -1)
165
/** Invalidate the pointers in a list node.
166
@param NAME list name
167
@param N pointer to the node that was removed */
168
# define UT_LIST_REMOVE_CLEAR(NAME, N)
171
/*******************************************************************//**
172
Removes a node from a two-way linked list.
173
@param NAME list name
174
@param BASE the base node (not a pointer to it)
175
@param N pointer to the node to be removed from the list
177
#define UT_LIST_REMOVE(NAME, BASE, N) \
180
ut_a((BASE).count > 0); \
182
if (((N)->NAME).next != NULL) { \
183
((((N)->NAME).next)->NAME).prev = ((N)->NAME).prev; \
185
(BASE).end = ((N)->NAME).prev; \
187
if (((N)->NAME).prev != NULL) { \
188
((((N)->NAME).prev)->NAME).next = ((N)->NAME).next; \
190
(BASE).start = ((N)->NAME).next; \
192
UT_LIST_REMOVE_CLEAR(NAME, N); \
195
/********************************************************************//**
196
Gets the next node in a two-way list.
197
@param NAME list name
198
@param N pointer to a node
199
@return the successor of N in NAME, or NULL */
200
#define UT_LIST_GET_NEXT(NAME, N)\
203
/********************************************************************//**
204
Gets the previous node in a two-way list.
205
@param NAME list name
206
@param N pointer to a node
207
@return the predecessor of N in NAME, or NULL */
208
#define UT_LIST_GET_PREV(NAME, N)\
211
/********************************************************************//**
212
Alternative macro to get the number of nodes in a two-way list, i.e.,
214
@param BASE the base node (not a pointer to it).
215
@return the number of nodes in the list */
216
#define UT_LIST_GET_LEN(BASE)\
219
/********************************************************************//**
220
Gets the first node in a two-way list.
221
@param BASE the base node (not a pointer to it)
222
@return first node, or NULL if the list is empty */
223
#define UT_LIST_GET_FIRST(BASE)\
226
/********************************************************************//**
227
Gets the last node in a two-way list.
228
@param BASE the base node (not a pointer to it)
229
@return last node, or NULL if the list is empty */
231
#define UT_LIST_GET_LAST(BASE)\
234
#define UT_LIST_GET_LAST(BASE) (BASE= NULL)
237
/********************************************************************//**
238
Checks the consistency of a two-way list.
239
@param NAME the name of the list
240
@param TYPE node type
241
@param BASE base node (not a pointer to it)
242
@param ASSERTION a condition on ut_list_node_313 */
243
#define UT_LIST_VALIDATE(NAME, TYPE, BASE, ASSERTION) \
245
ulint ut_list_i_313; \
246
TYPE* ut_list_node_313; \
248
ut_list_node_313 = (BASE).start; \
250
for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
251
ut_a(ut_list_node_313); \
253
ut_ad((ut_list_node_313->NAME).next || !ut_list_i_313); \
254
ut_list_node_313 = (ut_list_node_313->NAME).next; \
257
ut_a(ut_list_node_313 == NULL); \
259
ut_list_node_313 = (BASE).end; \
261
for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \
262
ut_a(ut_list_node_313); \
264
ut_ad((ut_list_node_313->NAME).prev || !ut_list_i_313); \
265
ut_list_node_313 = (ut_list_node_313->NAME).prev; \
268
ut_a(ut_list_node_313 == NULL); \