2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Simple, non circular, double linked pointer list.
23 * @note Created because the properties of the standard circular list were not
24 * very well suited for the interference graph implementation.
25 * This list uses an obstack and a free-list to efficiently manage its
27 * @author Kimon Hoffmann
36 * Helper macro that returns a new uninitialized list element by either
37 * fetching one from the free-list or allocating a new one on the lists
39 * @param list the list for which to allocate the element.
40 * @return the newly allocated, uninitialized element.
42 static plist_element_t *allocate_element(plist_t* list)
44 plist_element_t *new_element;
46 if (list->first_free_element != NULL) {
47 new_element = list->first_free_element;
48 list->first_free_element = new_element->next;
49 new_element->next = NULL;
52 new_element = OALLOC(list->obst, plist_element_t);
58 plist_t *plist_new(void)
60 plist_t *list = (plist_t*) xmalloc(sizeof(*list) + sizeof(*list->obst));
62 list->obst = (struct obstack *)&list[1];
63 list->foreign_obstack = 0;
64 list->first_element = NULL;
65 list->last_element = NULL;
66 list->first_free_element = NULL;
67 list->element_count = 0;
69 obstack_init(list->obst);
73 plist_t *plist_obstack_new(struct obstack *obst)
75 plist_t *list = OALLOC(obst, plist_t);
78 list->foreign_obstack = 1;
79 list->first_element = NULL;
80 list->last_element = NULL;
81 list->first_free_element = NULL;
82 list->element_count = 0;
87 void plist_free(plist_t *list)
89 list->first_element = NULL;
90 list->last_element = NULL;
91 list->first_free_element = NULL;
92 list->element_count = 0;
94 if (! list->foreign_obstack) {
95 obstack_free(list->obst, NULL);
100 void plist_insert_back(plist_t *list, void *value)
102 if (list->last_element != NULL) {
103 plist_insert_after(list, list->last_element, value);
106 plist_element_t *newElement = allocate_element(list);
108 newElement->data = value;
109 newElement->prev = NULL;
110 newElement->next = NULL;
111 list->first_element = list->last_element = newElement;
112 list->element_count = 1;
116 void plist_insert_front(plist_t *list, void *value)
118 if (list->first_element != NULL) {
119 plist_insert_before(list, list->first_element, value);
122 plist_element_t *newElement = allocate_element(list);
124 newElement->data = value;
125 newElement->prev = NULL;
126 newElement->next = NULL;
127 list->first_element = list->last_element = newElement;
128 list->element_count = 1;
132 void plist_insert_before(plist_t *list, plist_element_t *element, void *value)
134 plist_element_t *prevElement;
135 plist_element_t *newElement = allocate_element(list);
137 newElement->data = value;
138 newElement->next = element;
139 prevElement = element->prev;
140 newElement->prev = prevElement;
142 if (prevElement != NULL) {
143 prevElement->next = newElement;
146 list->first_element = newElement;
149 element->prev = newElement;
150 ++list->element_count;
153 void plist_insert_after(plist_t* list, plist_element_t* element, void* value)
155 plist_element_t *nextElement;
156 plist_element_t *newElement = allocate_element(list);
158 newElement->data = value;
159 newElement->prev = element;
160 nextElement = element->next;
161 newElement->next = nextElement;
163 if (nextElement != NULL) {
164 nextElement->prev = newElement;
167 list->last_element = newElement;
170 element->next = newElement;
171 ++list->element_count;
174 int plist_has_value(plist_t *list, void *value)
176 plist_element_t *iter;
178 for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
179 if (plist_element_get_value(iter) == value)
186 plist_element_t *plist_find_value(plist_t *list, void *value)
188 plist_element_t *iter;
190 for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
191 if (plist_element_get_value(iter) == value)
198 void plist_erase(plist_t *list, plist_element_t *element)
200 plist_element_t *next_element = element->next;
201 plist_element_t *prev_element = element->prev;
203 if (next_element != NULL) {
204 next_element->prev = prev_element;
207 list->last_element = prev_element;
210 if (prev_element != NULL) {
211 prev_element->next = next_element;
214 list->first_element = next_element;
217 --list->element_count;
219 /* Clean the element and prepend it to the free list */
220 element->prev = NULL; /* The allocation code expects prev to be NULL */
221 element->next = list->first_free_element;
222 list->first_free_element = element;
225 void plist_clear(plist_t *list)
227 plist_element_t *curr_element = list->first_element;
229 while (curr_element != NULL) {
230 curr_element->prev = NULL;
231 curr_element = curr_element->next;
234 curr_element = list->last_element;
236 if (curr_element != NULL) {
237 curr_element->next = list->first_free_element;
240 list->first_free_element = list->first_element;
241 list->first_element = 0;
242 list->last_element = 0;
243 list->element_count = 0;