2 * Copyright (C) 1995-2007 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
21 * Simple, non circular, double linked pointer list.
22 * Created because the properties of the standard circular list were not
23 * very well suited for the interference graph implementation.
24 * This list uses an obstack and a free-list to efficiently manage its
26 * @author Kimon Hoffmann
29 * @note Until now the code is entirely untested so it probably contains
37 * Helper macro that returns a new uninitialized list element by either
38 * fetching one from the free-list or allocating a new one on the lists
40 * @param list the list for which to allocate the element.
41 * @return the newly allocated, uninitialized element.
43 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 = obstack_alloc(list->obst, sizeof(*new_element));
58 plist_t *plist_new(void) {
59 plist_t *list = xmalloc(sizeof(*list) + sizeof(*list->obst));
61 list->obst = (struct obstack *)&list[1];
62 list->foreign_obstack = 0;
63 list->first_element = NULL;
64 list->last_element = NULL;
65 list->first_free_element = NULL;
66 list->element_count = 0;
68 obstack_init(list->obst);
72 plist_t *plist_obstack_new(struct obstack *obst) {
73 plist_t *list = obstack_alloc(obst, sizeof(*list));
76 list->foreign_obstack = 1;
77 list->first_element = NULL;
78 list->last_element = NULL;
79 list->first_free_element = NULL;
80 list->element_count = 0;
85 void plist_free(plist_t *list) {
86 list->first_element = NULL;
87 list->last_element = NULL;
88 list->first_free_element = NULL;
89 list->element_count = 0;
91 if (! list->foreign_obstack) {
92 obstack_free(list->obst, NULL);
97 void plist_insert_back(plist_t *list, void *value) {
98 if (list->last_element != NULL) {
99 plist_insert_after(list, list->last_element, value);
102 plist_element_t *newElement = allocate_element(list);
104 newElement->data = value;
105 newElement->prev = NULL;
106 newElement->next = NULL;
107 list->first_element = list->last_element = newElement;
108 list->element_count = 1;
112 void plist_insert_front(plist_t *list, void *value) {
113 if (list->first_element != NULL) {
114 plist_insert_before(list, list->first_element, value);
117 plist_element_t *newElement = allocate_element(list);
119 newElement->data = value;
120 newElement->prev = NULL;
121 newElement->next = NULL;
122 list->first_element = list->last_element = newElement;
123 list->element_count = 1;
127 void plist_insert_before(plist_t *list, plist_element_t *element, void *value) {
128 plist_element_t *prevElement;
129 plist_element_t *newElement = allocate_element(list);
131 newElement->data = value;
132 newElement->next = element;
133 prevElement = element->prev;
134 newElement->prev = prevElement;
136 if (prevElement != NULL) {
137 prevElement->next = newElement;
140 list->first_element = newElement;
143 element->prev = newElement;
144 ++list->element_count;
147 void plist_insert_after(plist_t* list, plist_element_t* element, void* value) {
148 plist_element_t *nextElement;
149 plist_element_t *newElement = allocate_element(list);
151 newElement->data = value;
152 newElement->prev = element;
153 nextElement = element->next;
154 newElement->next = nextElement;
156 if (nextElement != NULL) {
157 nextElement->prev = newElement;
160 list->last_element = newElement;
163 element->next = newElement;
164 ++list->element_count;
167 int plist_has_value(plist_t *list, void *value) {
168 plist_element_t *iter;
170 for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
171 if (plist_element_get_value(iter) == value)
178 plist_element_t *plist_find_value(plist_t *list, void *value) {
179 plist_element_t *iter;
181 for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
182 if (plist_element_get_value(iter) == value)
189 void plist_erase(plist_t *list, plist_element_t *element) {
190 plist_element_t *next_element = element->next;
191 plist_element_t *prev_element = element->prev;
193 if (next_element != NULL) {
194 next_element->prev = prev_element;
197 list->last_element = prev_element;
200 if (prev_element != NULL) {
201 prev_element->next = next_element;
204 list->first_element = next_element;
207 --list->element_count;
209 /* Clean the element and prepend it to the free list */
210 element->prev = NULL; /* The allocation code expects prev to be NULL */
211 element->next = list->first_free_element;
212 list->first_free_element = element;
215 void plist_clear(plist_t *list) {
216 plist_element_t *curr_element = list->first_element;
218 while (curr_element != NULL) {
219 curr_element->prev = NULL;
220 curr_element = curr_element->next;
223 curr_element = list->last_element;
225 if (curr_element != NULL) {
226 curr_element->next = list->first_free_element;
229 list->first_free_element = list->first_element;
230 list->first_element = 0;
231 list->last_element = 0;
232 list->element_count = 0;