Merged trunk and subtype.
[cacao.git] / src / toolbox / list.c
1 /* src/toolbox/list.c - double linked list
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31
32 #include "mm/memory.h"
33
34 #include "threads/mutex.hpp"
35
36 #include "toolbox/list.h"
37
38
39 /* list_create *****************************************************************
40
41    Allocates a new list and initializes the lock object.
42
43 *******************************************************************************/
44
45 list_t *list_create(int nodeoffset)
46 {
47         list_t *l;
48
49         l = NEW(list_t);
50
51         l->mutex      = Mutex_new();
52         l->first      = NULL;
53         l->last       = NULL;
54         l->nodeoffset = nodeoffset;
55         l->size       = 0;
56
57         return l;
58 }
59
60
61 /* list_free *******************************************************************
62
63    Free a list.
64
65 *******************************************************************************/
66
67 void list_free(list_t *l)
68 {
69         assert(l != NULL);
70
71         Mutex_delete(l->mutex);
72
73         FREE(l, list_t);
74 }
75
76
77 /* list_create_dump ************************************************************
78
79    Allocates a new list on the dump memory.
80
81    ATTENTION: This list does NOT initialize the locking object!!!
82
83 *******************************************************************************/
84
85 list_t *list_create_dump(int nodeoffset)
86 {
87         list_t *l;
88
89         l = DumpMemory_allocate(sizeof(list_t));
90
91         l->mutex      = NULL;
92         l->first      = NULL;
93         l->last       = NULL;
94         l->nodeoffset = nodeoffset;
95         l->size       = 0;
96
97         return l;
98 }
99
100
101 /* list_lock *******************************************************************
102
103    Locks the list.
104
105 *******************************************************************************/
106
107 void list_lock(list_t *l)
108 {
109         Mutex_lock(l->mutex);
110 }
111
112
113 /* list_unlock *****************************************************************
114
115    Unlocks the list.
116
117 *******************************************************************************/
118
119 void list_unlock(list_t *l)
120 {
121         Mutex_unlock(l->mutex);
122 }
123
124
125 /* list_add_first **************************************************************
126
127    Adds the element as first element.
128
129 *******************************************************************************/
130
131 void list_add_first(list_t *l, void *element)
132 {
133         listnode_t *ln;
134
135         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
136
137         if (l->first) {
138                 ln->prev       = NULL;
139                 ln->next       = l->first;
140                 l->first->prev = ln;
141                 l->first       = ln;
142         }
143         else {
144                 ln->prev = NULL;
145                 ln->next = NULL;
146                 l->last  = ln;
147                 l->first = ln;
148         }
149
150         /* Increase number of elements. */
151
152         l->size++;
153 }
154
155
156 /* list_add_last ***************************************************************
157
158    Adds the element as last element.
159
160 *******************************************************************************/
161
162 void list_add_last(list_t *l, void *element)
163 {
164         listnode_t *ln;
165
166         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
167
168         if (l->last) {
169                 ln->prev      = l->last;
170                 ln->next      = NULL;
171                 l->last->next = ln;
172                 l->last       = ln;
173         }
174         else {
175                 ln->prev = NULL;
176                 ln->next = NULL;
177                 l->last  = ln;
178                 l->first = ln;
179         }
180
181         /* Increase number of elements. */
182
183         l->size++;
184 }
185
186
187 /* list_add_before *************************************************************
188
189    Adds the element newelement to the list l before element.
190
191    [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
192
193 *******************************************************************************/
194
195 void list_add_before(list_t *l, void *element, void *newelement)
196 {
197         listnode_t *ln;
198         listnode_t *newln;
199
200         ln    = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
201         newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
202
203         /* Set the new links. */
204
205         newln->prev = ln->prev;
206         newln->next = ln;
207
208         if (newln->prev)
209                 newln->prev->next = newln;
210
211         ln->prev = newln;
212
213         /* set list's first and last if necessary */
214
215         if (l->first == ln)
216                 l->first = newln;
217
218         if (l->last == ln)
219                 l->last = newln;
220
221         /* Increase number of elements. */
222
223         l->size++;
224 }
225
226
227 /* list_remove ***************************************************************
228
229    Removes the element.
230
231 *******************************************************************************/
232
233 void list_remove(list_t *l, void *element)
234 {
235         listnode_t *ln;
236
237         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
238         
239         if (ln->next)
240                 ln->next->prev = ln->prev;
241         else
242                 l->last = ln->prev;
243
244         if (ln->prev)
245                 ln->prev->next = ln->next;
246         else
247                 l->first = ln->next;
248
249         ln->next = NULL;
250         ln->prev = NULL;
251
252         /* Decrease number of elements. */
253
254         l->size--;
255 }
256
257  
258 /* list_first ******************************************************************
259
260    Returns the first element of the list.
261
262 *******************************************************************************/
263
264 void *list_first(list_t *l)
265 {
266         void *el;
267
268         if (l->first == NULL)
269                 el = NULL;
270         else
271                 el = ((uint8_t *) l->first) - l->nodeoffset;
272
273         return el;
274 }
275
276
277 /* list_last *******************************************************************
278
279    Returns the last element of the list.
280
281 *******************************************************************************/
282
283 void *list_last(list_t *l)
284 {
285         void *el;
286
287         if (l->last == NULL)
288                 el = NULL;
289         else
290                 el = ((uint8_t *) l->last) - l->nodeoffset;
291
292         return el;
293 }
294
295
296 /* list_next *******************************************************************
297
298    Returns the next element of element from the list.
299
300 *******************************************************************************/
301
302 void *list_next(list_t *l, void *element)
303 {
304         listnode_t *ln;
305         void       *el;
306
307         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
308
309         if (ln->next == NULL)
310                 el = NULL;
311         else
312                 el = ((uint8_t *) ln->next) - l->nodeoffset;
313
314         return el;
315 }
316
317         
318 /* list_prev *******************************************************************
319
320    Returns the previous element of element from the list.
321
322 *******************************************************************************/
323
324 void *list_prev(list_t *l, void *element)
325 {
326         listnode_t *ln;
327         void       *el;
328
329         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
330
331         if (ln->prev == NULL)
332                 el = NULL;
333         else
334                 el = ((uint8_t *) ln->prev) - l->nodeoffset;
335
336         return el;
337 }
338
339
340 /*
341  * These are local overrides for various environment variables in Emacs.
342  * Please do not remove this and leave it at the end of the file, where
343  * Emacs will automagically detect them.
344  * ---------------------------------------------------------------------
345  * Local variables:
346  * mode: c
347  * indent-tabs-mode: t
348  * c-basic-offset: 4
349  * tab-width: 4
350  * End:
351  */