2 * Simple, non circular, double linked pointer list.
3 * Created because the properties of the standard circular list were not
4 * very well suited for the interference graph implementation.
5 * This list uses an obstack and a free-list to efficiently manage its
7 * @author Kimon Hoffmann
10 * @note Until now the code is entirely untested so it probably contains
18 * Helper macro that returns a new uninitialized list element by either
19 * fetching one from the free-list or allocating a new one on the lists
21 * @param list the list for which to allocate the element.
22 * @return the newly allocated, uninitialized element.
24 static plist_element_t *allocate_element(plist_t* list) {
25 plist_element_t *new_element;
27 if (list->first_free_element != NULL) {
28 new_element = list->first_free_element;
29 list->first_free_element = new_element->next;
30 new_element->next = NULL;
33 new_element = obstack_alloc(list->obst, sizeof(*new_element));
39 plist_t *plist_new(void) {
40 plist_t *list = xmalloc(sizeof(*list) + sizeof(*list->obst));
42 list->obst = (struct obstack *)&list[1];
43 list->foreign_obstack = 0;
44 list->first_element = NULL;
45 list->last_element = NULL;
46 list->first_free_element = NULL;
47 list->element_count = 0;
49 obstack_init(list->obst);
53 plist_t *plist_obstack_new(struct obstack *obst) {
54 plist_t *list = obstack_alloc(obst, sizeof(*list));
57 list->foreign_obstack = 1;
58 list->first_element = NULL;
59 list->last_element = NULL;
60 list->first_free_element = NULL;
61 list->element_count = 0;
66 void plist_free(plist_t *list) {
67 list->first_element = NULL;
68 list->last_element = NULL;
69 list->first_free_element = NULL;
70 list->element_count = 0;
72 if (! list->foreign_obstack) {
73 obstack_free(list->obst, NULL);
78 void plist_insert_back(plist_t *list, void *value) {
79 if (list->last_element != NULL) {
80 plist_insert_after(list, list->last_element, value);
83 plist_element_t *newElement = allocate_element(list);
85 newElement->data = value;
86 newElement->prev = NULL;
87 newElement->next = NULL;
88 list->first_element = list->last_element = newElement;
89 list->element_count = 1;
93 void plist_insert_front(plist_t *list, void *value) {
94 if (list->first_element != NULL) {
95 plist_insert_before(list, list->first_element, value);
98 plist_element_t *newElement = allocate_element(list);
100 newElement->data = value;
101 newElement->prev = NULL;
102 newElement->next = NULL;
103 list->first_element = list->last_element = newElement;
104 list->element_count = 1;
108 void plist_insert_before(plist_t *list, plist_element_t *element, void *value) {
109 plist_element_t *prevElement;
110 plist_element_t *newElement = allocate_element(list);
112 newElement->data = value;
113 newElement->next = element;
114 prevElement = element->prev;
115 newElement->prev = prevElement;
117 if (prevElement != NULL) {
118 prevElement->next = newElement;
121 list->first_element = newElement;
124 element->prev = newElement;
125 ++list->element_count;
128 void plist_insert_after(plist_t* list, plist_element_t* element, void* value) {
129 plist_element_t *nextElement;
130 plist_element_t *newElement = allocate_element(list);
132 newElement->data = value;
133 newElement->prev = element;
134 nextElement = element->next;
135 newElement->next = nextElement;
137 if (nextElement != NULL) {
138 nextElement->prev = newElement;
141 list->last_element = newElement;
144 element->next = newElement;
145 ++list->element_count;
148 int plist_has_value(plist_t *list, void *value) {
149 plist_element_t *iter;
151 for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
152 if (plist_element_get_value(iter) == value)
159 plist_element_t *plist_find_value(plist_t *list, void *value) {
160 plist_element_t *iter;
162 for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
163 if (plist_element_get_value(iter) == value)
170 void plist_erase(plist_t *list, plist_element_t *element) {
171 plist_element_t *next_element = element->next;
172 plist_element_t *prev_element = element->prev;
174 if (next_element != NULL) {
175 next_element->prev = prev_element;
178 list->last_element = prev_element;
181 if (prev_element != NULL) {
182 prev_element->next = next_element;
185 list->first_element = next_element;
188 --list->element_count;
190 /* Clean the element and prepend it to the free list */
191 element->prev = NULL; /* The allocation code expects prev to be NULL */
192 element->next = list->first_free_element;
193 list->first_free_element = element;
196 void plist_clear(plist_t *list) {
197 plist_element_t *curr_element = list->first_element;
199 while (curr_element != NULL) {
200 curr_element->prev = NULL;
201 curr_element = curr_element->next;
204 curr_element = list->last_element;
206 if (curr_element != NULL) {
207 curr_element->next = list->first_free_element;
210 list->first_free_element = list->first_element;
211 list->first_element = 0;
212 list->last_element = 0;
213 list->element_count = 0;