summaryrefslogtreecommitdiff
path: root/storage/xtradb/include/ut0lst.h
blob: 245dfc226c3cab960925f44fe5a188353b3f0b92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*****************************************************************************

Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA

*****************************************************************************/

/******************************************************************//**
@file include/ut0lst.h
List utilities

Created 9/10/1995 Heikki Tuuri
***********************************************************************/

#ifndef ut0lst_h
#define ut0lst_h

#include "univ.i"

/* This module implements the two-way linear list which should be used
if a list is used in the database. Note that a single struct may belong
to two or more lists, provided that the list are given different names.
An example of the usage of the lists can be found in fil0fil.c. */

/*******************************************************************//**
This macro expands to the unnamed type definition of a struct which acts
as the two-way list base node. The base node contains pointers
to both ends of the list and a count of nodes in the list (excluding
the base node from the count).
@param TYPE	the name of the list node data type */
#define UT_LIST_BASE_NODE_T(TYPE)\
struct {\
	ulint	count;	/*!< count of nodes in list */\
	TYPE *	start;	/*!< pointer to list start, NULL if empty */\
	TYPE *	end;	/*!< pointer to list end, NULL if empty */\
}\

/*******************************************************************//**
This macro expands to the unnamed type definition of a struct which
should be embedded in the nodes of the list, the node type must be a struct.
This struct contains the pointers to next and previous nodes in the list.
The name of the field in the node struct should be the name given
to the list.
@param TYPE	the list node type name */
/* Example:
typedef struct LRU_node_struct	LRU_node_t;
struct LRU_node_struct {
	UT_LIST_NODE_T(LRU_node_t)	LRU_list;
	...
}
The example implements an LRU list of name LRU_list. Its nodes are of type
LRU_node_t. */

#define UT_LIST_NODE_T(TYPE)\
struct {\
	TYPE *	prev;	/*!< pointer to the previous node,\
			NULL if start of list */\
	TYPE *	next;	/*!< pointer to next node, NULL if end of list */\
}\

/*******************************************************************//**
Initializes the base node of a two-way list.
@param BASE	the list base node
*/
#define UT_LIST_INIT(BASE)\
{\
	(BASE).count = 0;\
	(BASE).start = NULL;\
	(BASE).end   = NULL;\
}\

/*******************************************************************//**
Adds the node as the first element in a two-way linked list.
@param NAME	list name
@param BASE	the base node (not a pointer to it)
@param N	pointer to the node to be added to the list.
*/
#define UT_LIST_ADD_FIRST(NAME, BASE, N)\
{\
	ut_ad(N);\
	((BASE).count)++;\
	((N)->NAME).next = (BASE).start;\
	((N)->NAME).prev = NULL;\
	if (UNIV_LIKELY((BASE).start != NULL)) {\
		ut_ad((BASE).start != (N));\
		(((BASE).start)->NAME).prev = (N);\
	}\
	(BASE).start = (N);\
	if (UNIV_UNLIKELY((BASE).end == NULL)) {\
		(BASE).end = (N);\
	}\
}\

/*******************************************************************//**
Adds the node as the last element in a two-way linked list.
@param NAME	list name
@param BASE	the base node (not a pointer to it)
@param N	pointer to the node to be added to the list
*/
#define UT_LIST_ADD_LAST(NAME, BASE, N)\
{\
	ut_ad(N);\
	((BASE).count)++;\
	((N)->NAME).prev = (BASE).end;\
	((N)->NAME).next = NULL;\
	if ((BASE).end != NULL) {\
		ut_ad((BASE).end != (N));\
		(((BASE).end)->NAME).next = (N);\
	}\
	(BASE).end = (N);\
	if ((BASE).start == NULL) {\
		(BASE).start = (N);\
	}\
}\

/*******************************************************************//**
Inserts a NODE2 after NODE1 in a list.
@param NAME	list name
@param BASE	the base node (not a pointer to it)
@param NODE1	pointer to node after which NODE2 is inserted
@param NODE2	pointer to node being inserted after NODE1
*/
#define UT_LIST_INSERT_AFTER(NAME, BASE, NODE1, NODE2)\
{\
	ut_ad(NODE1);\
	ut_ad(NODE2);\
	ut_ad((NODE1) != (NODE2));\
	((BASE).count)++;\
	((NODE2)->NAME).prev = (NODE1);\
	((NODE2)->NAME).next = ((NODE1)->NAME).next;\
	if (((NODE1)->NAME).next != NULL) {\
		((((NODE1)->NAME).next)->NAME).prev = (NODE2);\
	}\
	((NODE1)->NAME).next = (NODE2);\
	if ((BASE).end == (NODE1)) {\
		(BASE).end = (NODE2);\
	}\
}\

#ifdef UNIV_LIST_DEBUG
/** Invalidate the pointers in a list node.
@param NAME	list name
@param N	pointer to the node that was removed */
# define UT_LIST_REMOVE_CLEAR(NAME, N)		\
((N)->NAME.prev = (N)->NAME.next = (void*) -1)
#else
/** Invalidate the pointers in a list node.
@param NAME	list name
@param N	pointer to the node that was removed */
# define UT_LIST_REMOVE_CLEAR(NAME, N) do {} while (0)
#endif

/*******************************************************************//**
Removes a node from a two-way linked list.
@param NAME	list name
@param BASE	the base node (not a pointer to it)
@param N	pointer to the node to be removed from the list
*/
#define UT_LIST_REMOVE(NAME, BASE, N)					\
do {									\
	ut_ad(N);							\
	ut_a((BASE).count > 0);						\
	((BASE).count)--;						\
	if (((N)->NAME).next != NULL) {					\
		((((N)->NAME).next)->NAME).prev = ((N)->NAME).prev;	\
	} else {							\
		(BASE).end = ((N)->NAME).prev;				\
	}								\
	if (((N)->NAME).prev != NULL) {					\
		((((N)->NAME).prev)->NAME).next = ((N)->NAME).next;	\
	} else {							\
		(BASE).start = ((N)->NAME).next;			\
	}								\
	UT_LIST_REMOVE_CLEAR(NAME, N);					\
} while (0)

/********************************************************************//**
Gets the next node in a two-way list.
@param NAME	list name
@param N	pointer to a node
@return		the successor of N in NAME, or NULL */
#define UT_LIST_GET_NEXT(NAME, N)\
	(((N)->NAME).next)

/********************************************************************//**
Gets the previous node in a two-way list.
@param NAME	list name
@param N	pointer to a node
@return		the predecessor of N in NAME, or NULL */
#define UT_LIST_GET_PREV(NAME, N)\
	(((N)->NAME).prev)

/********************************************************************//**
Alternative macro to get the number of nodes in a two-way list, i.e.,
its length.
@param BASE	the base node (not a pointer to it).
@return		the number of nodes in the list */
#define UT_LIST_GET_LEN(BASE)\
	(BASE).count

/********************************************************************//**
Gets the first node in a two-way list.
@param BASE	the base node (not a pointer to it)
@return		first node, or NULL if the list is empty */
#define UT_LIST_GET_FIRST(BASE)\
	(BASE).start

/********************************************************************//**
Gets the last node in a two-way list.
@param BASE	the base node (not a pointer to it)
@return		last node, or NULL if the list is empty */
#define UT_LIST_GET_LAST(BASE)\
	(BASE).end

/********************************************************************//**
Checks the consistency of a two-way list.
@param NAME		the name of the list
@param TYPE		node type
@param BASE		base node (not a pointer to it)
@param ASSERTION	a condition on ut_list_node_313 */
#define UT_LIST_VALIDATE(NAME, TYPE, BASE, ASSERTION)			\
do {									\
	ulint	ut_list_i_313;						\
	TYPE*	ut_list_node_313;					\
									\
	ut_list_node_313 = (BASE).start;				\
									\
	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
		ut_a(ut_list_node_313);					\
		ASSERTION;						\
		ut_ad((ut_list_node_313->NAME).next || !ut_list_i_313);	\
		ut_list_node_313 = (ut_list_node_313->NAME).next;	\
	}								\
									\
	ut_a(ut_list_node_313 == NULL);					\
									\
	ut_list_node_313 = (BASE).end;					\
									\
	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
		ut_a(ut_list_node_313);					\
		ASSERTION;						\
		ut_ad((ut_list_node_313->NAME).prev || !ut_list_i_313);	\
		ut_list_node_313 = (ut_list_node_313->NAME).prev;	\
	}								\
									\
	ut_a(ut_list_node_313 == NULL);					\
} while (0)

/********************************************************************//**
Align nodes with moving location.
@param NAME		the name of the list
@param TYPE		node type
@param BASE		base node (not a pointer to it)
@param OFFSET		offset moved */
#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET)	\
do {									\
	ulint	ut_list_i_313;						\
	TYPE*	ut_list_node_313;					\
									\
	if ((BASE).start)						\
		(BASE).start = (void*)((byte*)((BASE).start)			\
			+ (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\
	if ((BASE).end)							\
		(BASE).end   = (void*)((byte*)((BASE).end)			\
			+ (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\
									\
	ut_list_node_313 = (BASE).start;				\
									\
	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
		ut_a(ut_list_node_313);					\
		if ((ut_list_node_313->NAME).prev)			\
			(ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\
				+ (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\
		if ((ut_list_node_313->NAME).next)			\
			(ut_list_node_313->NAME).next =	(void*)((byte*)((ut_list_node_313->NAME).next)\
				+ (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\
		ut_list_node_313 = (ut_list_node_313->NAME).next;	\
	}								\
									\
	ut_a(ut_list_node_313 == NULL);					\
									\
	ut_list_node_313 = (BASE).end;					\
									\
	for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) {		\
		ut_a(ut_list_node_313);					\
		ut_list_node_313 = (ut_list_node_313->NAME).prev;	\
	}								\
									\
	ut_a(ut_list_node_313 == NULL);					\
} while (0)

#endif