InnoDB Plugin  1.0
ut0lst.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
4 
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.
8 
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.
12 
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.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /******************************************************************/
26 #ifndef ut0lst_h
27 #define ut0lst_h
28 
29 #include "univ.i"
30 
31 /*******************************************************************/
35 #define IB_OFFSETOF(T, F) \
36  (reinterpret_cast<byte*>(&(T)->F) - reinterpret_cast<byte*>(T))
37 
38 /* This module implements the two-way linear list which should be used
39 if a list is used in the database. Note that a single struct may belong
40 to two or more lists, provided that the list are given different names.
41 An example of the usage of the lists can be found in fil0fil.cc. */
42 
43 /*******************************************************************/
49 template <typename TYPE>
50 struct ut_list_base {
51  typedef TYPE elem_type;
52 
53  ulint count;
54  TYPE* start;
55  TYPE* end;
56 };
57 
58 #define UT_LIST_BASE_NODE_T(TYPE) ut_list_base<TYPE>
59 
60 /*******************************************************************/
67 /* Example:
68 struct LRU_node_t {
69  UT_LIST_NODE_T(LRU_node_t) LRU_list;
70  ...
71 }
72 The example implements an LRU list of name LRU_list. Its nodes are of type
73 LRU_node_t. */
74 
75 template <typename TYPE>
76 struct ut_list_node {
77  TYPE* prev;
79  TYPE* next;
80 };
81 
82 #define UT_LIST_NODE_T(TYPE) ut_list_node<TYPE>
83 
84 /*******************************************************************/
89 template <typename Type>
91 ut_elem_get_node(Type& elem, size_t offset)
92 {
93  ut_a(offset < sizeof(elem));
94 
95  return(*reinterpret_cast<ut_list_node<Type>*>(
96  reinterpret_cast<byte*>(&elem) + offset));
97 }
98 
99 /*******************************************************************/
103 #define UT_LIST_INIT(BASE)\
104 {\
105  (BASE).count = 0;\
106  (BASE).start = NULL;\
107  (BASE).end = NULL;\
108 }\
109 
110 /*******************************************************************/
115 template <typename List, typename Type>
116 void
118  List& list,
119  Type& elem,
120  size_t offset)
121 {
122  ut_list_node<Type>& elem_node = ut_elem_get_node(elem, offset);
123 
124  elem_node.prev = 0;
125  elem_node.next = list.start;
126 
127  if (list.start != 0) {
128  ut_list_node<Type>& base_node =
129  ut_elem_get_node(*list.start, offset);
130 
131  ut_ad(list.start != &elem);
132 
133  base_node.prev = &elem;
134  }
135 
136  list.start = &elem;
137 
138  if (list.end == 0) {
139  list.end = &elem;
140  }
141 
142  ++list.count;
143 }
144 
145 /*******************************************************************/
150 #define UT_LIST_ADD_FIRST(NAME, LIST, ELEM) \
151  ut_list_prepend(LIST, *ELEM, IB_OFFSETOF(ELEM, NAME))
152 
153 /*******************************************************************/
158 template <typename List, typename Type>
159 void
161  List& list,
162  Type& elem,
163  size_t offset)
164 {
165  ut_list_node<Type>& elem_node = ut_elem_get_node(elem, offset);
166 
167  elem_node.next = 0;
168  elem_node.prev = list.end;
169 
170  if (list.end != 0) {
171  ut_list_node<Type>& base_node =
172  ut_elem_get_node(*list.end, offset);
173 
174  ut_ad(list.end != &elem);
175 
176  base_node.next = &elem;
177  }
178 
179  list.end = &elem;
180 
181  if (list.start == 0) {
182  list.start = &elem;
183  }
184 
185  ++list.count;
186 }
187 
188 /*******************************************************************/
193 #define UT_LIST_ADD_LAST(NAME, LIST, ELEM)\
194  ut_list_append(LIST, *ELEM, IB_OFFSETOF(ELEM, NAME))
195 
196 /*******************************************************************/
202 template <typename List, typename Type>
203 void
205  List& list,
206  Type& elem1,
207  Type& elem2,
208  size_t offset)
209 {
210  ut_ad(&elem1 != &elem2);
211 
212  ut_list_node<Type>& elem1_node = ut_elem_get_node(elem1, offset);
213  ut_list_node<Type>& elem2_node = ut_elem_get_node(elem2, offset);
214 
215  elem2_node.prev = &elem1;
216  elem2_node.next = elem1_node.next;
217 
218  if (elem1_node.next != NULL) {
219  ut_list_node<Type>& next_node =
220  ut_elem_get_node(*elem1_node.next, offset);
221 
222  next_node.prev = &elem2;
223  }
224 
225  elem1_node.next = &elem2;
226 
227  if (list.end == &elem1) {
228  list.end = &elem2;
229  }
230 
231  ++list.count;
232 }
233 
234 /*******************************************************************/
240 #define UT_LIST_INSERT_AFTER(NAME, LIST, ELEM1, ELEM2)\
241  ut_list_insert(LIST, *ELEM1, *ELEM2, IB_OFFSETOF(ELEM1, NAME))
242 
243 #ifdef UNIV_LIST_DEBUG
244 
247 # define UT_LIST_REMOVE_CLEAR(N) \
248  (N).next = (Type*) -1; \
249  (N).prev = (N).next
250 #else
251 
254 # define UT_LIST_REMOVE_CLEAR(N)
255 #endif /* UNIV_LIST_DEBUG */
256 
257 /*******************************************************************/
262 template <typename List, typename Type>
263 void
265  List& list,
266  Type& elem,
267  size_t offset)
268 {
269  ut_list_node<Type>& elem_node = ut_elem_get_node(elem, offset);
270 
271  ut_a(list.count > 0);
272 
273  if (elem_node.next != NULL) {
274  ut_list_node<Type>& next_node =
275  ut_elem_get_node(*elem_node.next, offset);
276 
277  next_node.prev = elem_node.prev;
278  } else {
279  list.end = elem_node.prev;
280  }
281 
282  if (elem_node.prev != NULL) {
283  ut_list_node<Type>& prev_node =
284  ut_elem_get_node(*elem_node.prev, offset);
285 
286  prev_node.next = elem_node.next;
287  } else {
288  list.start = elem_node.next;
289  }
290 
291  UT_LIST_REMOVE_CLEAR(elem_node);
292 
293  --list.count;
294 }
295 
296 /*******************************************************************/
301 #define UT_LIST_REMOVE(NAME, LIST, ELEM) \
302  ut_list_remove(LIST, *ELEM, IB_OFFSETOF(ELEM, NAME))
303 
304 /********************************************************************/
309 #define UT_LIST_GET_NEXT(NAME, N)\
310  (((N)->NAME).next)
311 
312 /********************************************************************/
317 #define UT_LIST_GET_PREV(NAME, N)\
318  (((N)->NAME).prev)
319 
320 /********************************************************************/
325 #define UT_LIST_GET_LEN(BASE)\
326  (BASE).count
327 
328 /********************************************************************/
332 #define UT_LIST_GET_FIRST(BASE)\
333  (BASE).start
334 
335 /********************************************************************/
339 #define UT_LIST_GET_LAST(BASE)\
340  (BASE).end
341 
342 struct NullValidate { void operator()(const void* elem) { } };
343 
344 /********************************************************************/
349 template <typename List, class Functor>
350 void
352  List& list,
354  List::elem_type::*node,
355  Functor functor)
356 {
357  ulint count = 0;
358 
359  for (typename List::elem_type* elem = list.start;
360  elem != 0;
361  elem = (elem->*node).next, ++count) {
362 
363  functor(elem);
364  }
365 
366  ut_a(count == list.count);
367 }
368 
369 /********************************************************************/
374 template <typename List, class Functor>
375 void
377  List& list,
379  List::elem_type::*node,
380  Functor functor = NullValidate())
381 {
382  ut_list_map(list, node, functor);
383 
384  ulint count = 0;
385 
386  for (typename List::elem_type* elem = list.end;
387  elem != 0;
388  elem = (elem->*node).prev, ++count) {
389 
390  functor(elem);
391  }
392 
393  ut_a(count == list.count);
394 }
395 
396 /********************************************************************/
402 #define UT_LIST_VALIDATE(NAME, TYPE, LIST, FUNCTOR) \
403  ut_list_validate(LIST, &TYPE::NAME, FUNCTOR)
404 
405 #define UT_LIST_CHECK(NAME, TYPE, LIST) \
406  ut_list_validate(LIST, &TYPE::NAME, NullValidate())
407 
408 #endif /* ut0lst.h */