1 | /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: |
3 | #ident "$Id$" |
4 | /*====== |
5 | This file is part of PerconaFT. |
6 | |
7 | |
8 | Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. |
9 | |
10 | PerconaFT is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU General Public License, version 2, |
12 | as published by the Free Software Foundation. |
13 | |
14 | PerconaFT is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | GNU General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
21 | |
22 | ---------------------------------------- |
23 | |
24 | PerconaFT is free software: you can redistribute it and/or modify |
25 | it under the terms of the GNU Affero General Public License, version 3, |
26 | as published by the Free Software Foundation. |
27 | |
28 | PerconaFT is distributed in the hope that it will be useful, |
29 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 | GNU Affero General Public License for more details. |
32 | |
33 | You should have received a copy of the GNU Affero General Public License |
34 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
35 | ======= */ |
36 | |
37 | #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." |
38 | |
39 | #pragma once |
40 | |
41 | // This toku_list is intended to be embedded in other data structures. |
42 | struct toku_list { |
43 | struct toku_list *next, *prev; |
44 | }; |
45 | |
46 | static inline int toku_list_num_elements_est(struct toku_list *head) { |
47 | if (head->next == head) return 0; |
48 | if (head->next == head->prev) return 1; |
49 | return 2; |
50 | } |
51 | |
52 | |
53 | static inline void toku_list_init(struct toku_list *head) { |
54 | head->next = head->prev = head; |
55 | } |
56 | |
57 | static inline int toku_list_empty(struct toku_list *head) { |
58 | return head->next == head; |
59 | } |
60 | |
61 | static inline struct toku_list *toku_list_head(struct toku_list *head) { |
62 | return head->next; |
63 | } |
64 | |
65 | static inline struct toku_list *toku_list_tail(struct toku_list *head) { |
66 | return head->prev; |
67 | } |
68 | |
69 | static inline void toku_list_insert_between(struct toku_list *a, struct toku_list *toku_list, struct toku_list *b) { |
70 | |
71 | toku_list->next = a->next; |
72 | toku_list->prev = b->prev; |
73 | a->next = b->prev = toku_list; |
74 | } |
75 | |
76 | static inline void toku_list_push(struct toku_list *head, struct toku_list *toku_list) { |
77 | toku_list_insert_between(head->prev, toku_list, head); |
78 | } |
79 | |
80 | static inline void toku_list_push_head(struct toku_list *head, struct toku_list *toku_list) { |
81 | toku_list_insert_between(head, toku_list, head->next); |
82 | } |
83 | |
84 | static inline void toku_list_remove(struct toku_list *toku_list) { |
85 | struct toku_list *prev = toku_list->prev; |
86 | struct toku_list *next = toku_list->next; |
87 | next->prev = prev; |
88 | prev->next = next; |
89 | toku_list_init(toku_list); // Set the toku_list element to be empty |
90 | } |
91 | |
92 | static inline struct toku_list *toku_list_pop(struct toku_list *head) { |
93 | struct toku_list *toku_list = head->prev; |
94 | toku_list_remove(toku_list); |
95 | return toku_list; |
96 | } |
97 | |
98 | static inline struct toku_list *toku_list_pop_head(struct toku_list *head) { |
99 | struct toku_list *toku_list = head->next; |
100 | toku_list_remove(toku_list); |
101 | return toku_list; |
102 | } |
103 | |
104 | static inline void toku_list_move(struct toku_list *newhead, struct toku_list *oldhead) { |
105 | struct toku_list *first = oldhead->next; |
106 | struct toku_list *last = oldhead->prev; |
107 | // assert(!toku_list_empty(oldhead)); |
108 | newhead->next = first; |
109 | newhead->prev = last; |
110 | last->next = first->prev = newhead; |
111 | toku_list_init(oldhead); |
112 | } |
113 | |
114 | // Note: Need the extra level of parens in these macros so that |
115 | // toku_list_struct(h, foo, b)->zot |
116 | // will work right. Otherwise the type cast will try to include ->zot, and it will be all messed up. |
117 | #if ((defined(__GNUC__) && __GNUC__ >= 4) || defined(__builtin_offsetof) ) && !defined(__clang__) |
118 | #define toku_list_struct(p, t, f) ((t*)((char*)(p) - __builtin_offsetof(t, f))) |
119 | #else |
120 | #define toku_list_struct(p, t, f) ((t*)((char*)(p) - ((char*)&((t*)0)->f))) |
121 | #endif |
122 | |