| 141 |
Kevin |
1 |
#ifndef __LIST_H
|
|
|
2 |
#define __LIST_H
|
|
|
3 |
/* This code is taken from the Pintos education OS.
|
|
|
4 |
* For copyright information, see www.pintos-os.org */
|
|
|
5 |
|
|
|
6 |
/* Doubly linked list.
|
|
|
7 |
|
|
|
8 |
This implementation of a doubly linked list does not require
|
|
|
9 |
use of dynamically allocated memory. Instead, each structure
|
|
|
10 |
that is a potential list element must embed a struct list_elem
|
|
|
11 |
member. All of the list functions operate on these `struct
|
|
|
12 |
list_elem's. The list_entry macro allows conversion from a
|
|
|
13 |
struct list_elem back to a structure object that contains it.
|
|
|
14 |
|
|
|
15 |
For example, suppose there is a needed for a list of `struct
|
|
|
16 |
foo'. `struct foo' should contain a `struct list_elem'
|
|
|
17 |
member, like so:
|
|
|
18 |
|
|
|
19 |
struct foo
|
|
|
20 |
{
|
|
|
21 |
struct list_elem elem;
|
|
|
22 |
int bar;
|
|
|
23 |
...other members...
|
|
|
24 |
};
|
|
|
25 |
|
|
|
26 |
Then a list of `struct foo' can be be declared and initialized
|
|
|
27 |
like so:
|
|
|
28 |
|
|
|
29 |
struct list foo_list;
|
|
|
30 |
|
|
|
31 |
list_init (&foo_list);
|
|
|
32 |
|
|
|
33 |
Iteration is a typical situation where it is necessary to
|
|
|
34 |
convert from a struct list_elem back to its enclosing
|
|
|
35 |
structure. Here's an example using foo_list:
|
|
|
36 |
|
|
|
37 |
struct list_elem *e;
|
|
|
38 |
|
|
|
39 |
for (e = list_begin (&foo_list); e != list_end (&foo_list);
|
|
|
40 |
e = list_next (e))
|
|
|
41 |
{
|
|
|
42 |
struct foo *f = list_entry (e, struct foo, elem);
|
|
|
43 |
...do something with f...
|
|
|
44 |
}
|
|
|
45 |
|
|
|
46 |
You can find real examples of list usage throughout the
|
|
|
47 |
source; for example, malloc.c, palloc.c, and thread.c in the
|
|
|
48 |
threads directory all use lists.
|
|
|
49 |
|
|
|
50 |
The interface for this list is inspired by the list<> template
|
|
|
51 |
in the C++ STL. If you're familiar with list<>, you should
|
|
|
52 |
find this easy to use. However, it should be emphasized that
|
|
|
53 |
these lists do *no* type checking and can't do much other
|
|
|
54 |
correctness checking. If you screw up, it will bite you.
|
|
|
55 |
|
|
|
56 |
Glossary of list terms:
|
|
|
57 |
|
|
|
58 |
- "front": The first element in a list. Undefined in an
|
|
|
59 |
empty list. Returned by list_front().
|
|
|
60 |
|
|
|
61 |
- "back": The last element in a list. Undefined in an empty
|
|
|
62 |
list. Returned by list_back().
|
|
|
63 |
|
|
|
64 |
- "tail": The element figuratively just after the last
|
|
|
65 |
element of a list. Well defined even in an empty list.
|
|
|
66 |
Returned by list_end(). Used as the end sentinel for an
|
|
|
67 |
iteration from front to back.
|
|
|
68 |
|
|
|
69 |
- "beginning": In a non-empty list, the front. In an empty
|
|
|
70 |
list, the tail. Returned by list_begin(). Used as the
|
|
|
71 |
starting point for an iteration from front to back.
|
|
|
72 |
|
|
|
73 |
- "head": The element figuratively just before the first
|
|
|
74 |
element of a list. Well defined even in an empty list.
|
|
|
75 |
Returned by list_rend(). Used as the end sentinel for an
|
|
|
76 |
iteration from back to front.
|
|
|
77 |
|
|
|
78 |
- "reverse beginning": In a non-empty list, the back. In an
|
|
|
79 |
empty list, the head. Returned by list_rbegin(). Used as
|
|
|
80 |
the starting point for an iteration from back to front.
|
|
|
81 |
|
|
|
82 |
- "interior element": An element that is not the head or
|
|
|
83 |
tail, that is, a real list element. An empty list does
|
|
|
84 |
not have any interior elements.
|
|
|
85 |
*/
|
|
|
86 |
|
|
|
87 |
#include <stdbool.h>
|
|
|
88 |
#include <stddef.h>
|
|
|
89 |
#include <stdint.h>
|
|
|
90 |
|
|
|
91 |
/* List element. */
|
|
|
92 |
struct list_elem
|
|
|
93 |
{
|
|
|
94 |
struct list_elem *prev; /* Previous list element. */
|
|
|
95 |
struct list_elem *next; /* Next list element. */
|
|
|
96 |
};
|
|
|
97 |
|
|
|
98 |
/* List. */
|
|
|
99 |
struct list
|
|
|
100 |
{
|
|
|
101 |
struct list_elem head; /* List head. */
|
|
|
102 |
struct list_elem tail; /* List tail. */
|
|
|
103 |
};
|
|
|
104 |
|
|
|
105 |
/* Converts pointer to list element LIST_ELEM into a pointer to
|
|
|
106 |
the structure that LIST_ELEM is embedded inside. Supply the
|
|
|
107 |
name of the outer structure STRUCT and the member name MEMBER
|
|
|
108 |
of the list element. See the big comment at the top of the
|
|
|
109 |
file for an example. */
|
|
|
110 |
#define list_entry(LIST_ELEM, STRUCT, MEMBER) \
|
|
|
111 |
((STRUCT *) ((uint8_t *) &(LIST_ELEM)->next \
|
|
|
112 |
- offsetof (STRUCT, MEMBER.next)))
|
|
|
113 |
|
|
|
114 |
void list_init (struct list *);
|
|
|
115 |
|
|
|
116 |
/* List traversal. */
|
|
|
117 |
struct list_elem *list_begin (struct list *);
|
|
|
118 |
struct list_elem *list_next (struct list_elem *);
|
|
|
119 |
struct list_elem *list_end (struct list *);
|
|
|
120 |
|
|
|
121 |
struct list_elem *list_rbegin (struct list *);
|
|
|
122 |
struct list_elem *list_prev (struct list_elem *);
|
|
|
123 |
struct list_elem *list_rend (struct list *);
|
|
|
124 |
|
|
|
125 |
struct list_elem *list_head (struct list *);
|
|
|
126 |
struct list_elem *list_tail (struct list *);
|
|
|
127 |
|
|
|
128 |
/* List insertion. */
|
|
|
129 |
void list_insert (struct list_elem *, struct list_elem *);
|
|
|
130 |
void list_splice (struct list_elem *before,
|
|
|
131 |
struct list_elem *first, struct list_elem *last);
|
|
|
132 |
void list_push_front (struct list *, struct list_elem *);
|
|
|
133 |
void list_push_back (struct list *, struct list_elem *);
|
|
|
134 |
|
|
|
135 |
/* List removal. */
|
|
|
136 |
struct list_elem *list_remove (struct list_elem *);
|
|
|
137 |
struct list_elem *list_pop_front (struct list *);
|
|
|
138 |
struct list_elem *list_pop_back (struct list *);
|
|
|
139 |
|
|
|
140 |
/* List elements. */
|
|
|
141 |
struct list_elem *list_front (struct list *);
|
|
|
142 |
struct list_elem *list_back (struct list *);
|
|
|
143 |
|
|
|
144 |
/* List properties. */
|
|
|
145 |
size_t list_size (struct list *);
|
|
|
146 |
bool list_empty (struct list *);
|
|
|
147 |
|
|
|
148 |
/* Miscellaneous. */
|
|
|
149 |
void list_reverse (struct list *);
|
|
|
150 |
|
|
|
151 |
/* Compares the value of two list elements A and B, given
|
|
|
152 |
auxiliary data AUX. Returns true if A is less than B, or
|
|
|
153 |
false if A is greater than or equal to B. */
|
|
|
154 |
typedef bool list_less_func (const struct list_elem *a,
|
|
|
155 |
const struct list_elem *b,
|
|
|
156 |
void *aux);
|
|
|
157 |
|
|
|
158 |
/* Operations on lists with ordered elements. */
|
|
|
159 |
void list_sort (struct list *,
|
|
|
160 |
list_less_func *, void *aux);
|
|
|
161 |
void list_insert_ordered (struct list *, struct list_elem *,
|
|
|
162 |
list_less_func *, void *aux);
|
|
|
163 |
void list_unique (struct list *, struct list *duplicates,
|
|
|
164 |
list_less_func *, void *aux);
|
|
|
165 |
|
|
|
166 |
/* Max and min. */
|
|
|
167 |
struct list_elem *list_max (struct list *, list_less_func *, void *aux);
|
|
|
168 |
struct list_elem *list_min (struct list *, list_less_func *, void *aux);
|
|
|
169 |
|
|
|
170 |
#endif /* list.h */
|